`

Java 基础问题全解答

    博客分类:
  • J2SE
阅读更多
1. 什么叫作抽象?

抽象是认识复杂现象过程中使用的思维工具,即抽出事物本质的共同的特性而暂不考虑它的细节,不考虑其他因素。

 
 

2.    面向对象编程的三个原则?

1、封装性(Encapsulation)
    封装提供了一种方法将代码和数据绑定到一起,保护两者的安全,防止外部接口的非法访问或误用.通过封装,组件的用户仅需要知道怎样和组件进行交互的方法,而不用知道组件是怎样设计和工作的,用什么语言设计的
2、继承性(Inheritance)
    继承,使一个组件可以继承另一个组件性能的属性
3、多态性(Ploymorphism)
    多态性是"一个接口,多种方法",指定组件实现哪些功能以及如何实现

 

3.    怎样定义一个标识符?
 
 
 

4.    java的关键字有哪些?NULL属于java的关键字吗?

  关键字列表
 

  abstract boolean break byte case
  catch char class continue default
  do double else extends false
  final finally float for if
  implements import instanceof int interface
  long native new null package
  private protected public return short
  static super switch synchronized this
  throw throws transient true try
  void volatile while
  保留字
  const,goto

 
 
 

5.    java的数据类型有哪些?分别说明一下?byte,short ,int ,long ,char ,float , double , boolean 分别是多少位?
 

  在Java语言中,数据类型可以分为两大类:基本类型、扩展类型。
Java 语言的基本数据类型包括:boolean、char、byte、int、short、long、float、double 八种:
  类型          描述                      取值范围

  Boolean      布尔型                     只有两个值true、false
  Char         字符型
  Byte         8位带符号整数               -128到127之间的任意整数
  Short        16位无符号整数              -32768~32767之间的任意整数
  Int          32位带符号整数              -231到231-1之间的任意整数
  Long         64位带符号整数              -263到263-1之间的任意整数
  Float        32位单精度浮点数            根据IEEE754-1985标准
  Double       64位双精度浮点数            根据IEEE754-1985标准

 
 
 

6.    列举一下常见的转义字符?
 

   Java语言中的转义字符:
\'     \\     \r     \n     \f     \t     \b    \ddd     \uxxxx  
例如:\071是ASCII码为八进制数71(十进制数57)的字符。
\u0041是Unicode码为十六进制数41(十进制数65)的字符。

 
 
 
 
 

7.    怎样定义java的数组类型?

1.type[] atrribute;
2.type atrribute[];

 
 
 

8.    列举出常见的算术运算符?并说明++a和a++的区别?

常见的算术运算符:
+            -        *        /         %            &&         ||          ++        --       >         <            =              |            &
 
++a与a++的区别是,如果++a与a++同时参与表达式运算,则++a在此表达式中的值为他此前所拥有之值加“1”,而a++则与此前之值一致。

 
 
 
 
 

9.    列举出常见的位运算符?
10.    列举出常见的关系运算符?
11.    列举出常见的布尔逻辑运算符?
12.    请写出一个三元运算符的例子?

1、   算术运算符(+,—,*,/,%,++,——):依次为加,减,乘,除,求余数。除最后两种是单目运算符外,其它几种都是双目运算符。前四种运算较简单,不再展开叙述,最后三种运算的定义如下:
Op1 % op2  表示:oPl—int(oP1/op2)*op2,其中ina(a)表示取a的整数部分(a的小数部分总非负)。
Op++ 表示 op = op +1;
Op-- 表示 op = op -1;
 
2.  关系运算符(>,>=, ==,<=,<,!=),    分别表示大于,大于等于,等于,小于等于,都是双目运算符,即运算结果是布尔型,即为true 或false。
 
3.  逻辑运算符(&&,|| , ! )    分别表示与,或,非。前两种是双日运算符,最后一种是单目运算符,参与运算的是布尔值,其结果也为布尔值。
 
4.  位运算符(~,&,  |,  ^     >>.<<,>>>)     依次为取反,按位与,按位或,按位异或,右移位,左移位,无符号右移位
 
5.  赋值运算符(=)  赋值操作符,它将等号右边数据的值赋值给左边的变量。
 
6.  条件运算柠(?:)
条件运算符为三目运算符,其—“般格式为:a>b?a:b
 
7.  扩展运算符(十=’—=,  *= , /=  ,%=,&=,|=,^=,>>=,<<=,>>>=)
    扩展运算符都是由一个双目运算符和一个等号连在一起组成(注意它们之间不能用空格隔开),以“+=”为例说明这类扩展运算符的用法:
A += B;  表示A = A+B     其它类似。
 
8  其他运算符,如豆号运算符“,”,分量运算符“· ”。再如实例运算符“instanceof”,内存分配运算符“new”,强制类型转换运算符“(类型)”,方法调用运算符“()”,取数组元素运算符“{ }”。
    比如,设t是类Thread的一个实例。
    分量运算符:t.name  表示类的实例的调用,又叫点问,(意指通过点的操作符访问类的实例对象)

 
 
 
 
 

13.    列举出运算符的优先级?

    优先顺序依次为(1级最优先,余下嗤?lt;FONT face="Times New Roman">)
第1级:.  ()
纪2级:++  --  !  ~  instanceof
第3级:new
第4级:*  / %
第5级:+   -
第6级:>>  >>>  <<
第7织:>  <  >=  <=
第8级:==   !=
第9级:&
第10级:^
第11级:!
第12级:&&
纪14级:?:
第13级:||
第15级:=  +=  -=  *=  /=
第16级:&=  !=  <<=  >>=   >>>=
记住这些优先次序是困难的,—个较好的方法是使用括号(),比如:

            a>b &&  b>c && c>a   可以用括号写为   ((a>b) && (b>c)) && (c>a) 这样即清晰易懂,也不易出错


 
 

14.    试着列举出java中程序控制语句的关键字?各给出一个例子?

  Java程序通过控制语句来控制程序流的执行,程序流是由若干个语句组成的,语句可以是单—的一条语句,也可以是大括号{}括起来的复合语句。
Java中的语句分为下面这几类:
 -分支语句:if—else, switch
 -循环语句:while, do-while, for
 -与程序转移有关的其他语句:break, continue, return
 -异常处理语句:try-catch-finally, throw
 -注释语句:// 单行注释, /*  */ 多行注释 ,/**  */ 程序注解注释       
 
下面我们分别介绍这些语句。
1.  条件语句if-else
if-else语句根据判定条件的真假来执行两种操作中的一种,格式如下:
if (布尔表达式)
         语句1;
   [else    语询2;]  
 
    其中,布尔表达式是任意一个返回布尔型数据的表达式,每个单一的语句后都必须有分号表示结束,语句1和语句2可以是单一语句,也可以是复合语句,复合语句用{}括起来,{}外面不
用加分号,else句子是任意可选的。
    如果布尔表达式的值为真,程序就执行语句1,否则就执行语句2。
 
表达式的每个单一的语句后都必须有分号表示结束,语句1和语句2可以是单一语句,也可以是复合语句,复合语句用{}括起来{}外面不用加分号,else句子是任意可选的。这里的复合语句是指由多个单一语句组合而成为实现某一个执行步骤的多个单一语句的集合,通常用{}括起来,这时{}里面的单一语句结束时一定要加分号,而在{}外面就不必要加分号,因为{}的作用只是让程序在执行过程中,将{}里的多个单一语句当作上面的if 语句将要选择的语句之一而已。
 
 
2.  多分支语句switch
 switch语句根据表达式的值来执行多个操作中的一个,格式如下:
    switch (expression)
    {
    case  value1 :  statement 1;
                     break;
    case  value2 :  statement 2;
                     break;
    case  value3 :  statement 3;
                     break;
                  ......
    case  valueN :  statement N;
                     break;
    [default    :  defaultSatement;]
    }
   值得注意的是,表达式 expression 的返回值类型必须是这几种类型之—:int,byte,char,short。case 语句中的值 value N 必须是常量,而且所有case语句中的值应是不同的。
    break语句用来在执行完一个case分支后,使程序跳出switch语句,即终止switch语句的执行。default子句是可选的。
 
    3.  循环语句
    Java中提供的循环语句有:while语句、do-while语句和for语句,循环语的作用就是反复执行—段代码,直到满足终止循环的条件为止。无论是上面哪种循环语句,通常包括下
面四个部分:
1)初始化部分
  该部分用来设置循环的一些初始条件,比如循环变量赋初值。
2)循环体部分
  循环体是指被反复执行的一段代码,可以是—条语句,也可以是复合语句。
3)迭代部分(修正部分)
  该部分常用来使计数器加1或者减1, 这部分内容在当前循环结束后、下一次循环开始前执行。
4)终止部分
这部分内容在当前循环结束后
  用来判定是否终止循环的语句,通常是一个布尔表达式,每一次循环都需要对这个表达式进行求值,以验证是否满足循环终止的条件。下面,我们分别介绍while、do—while和for循环语句。
 
While语句
while语句的格式为:
初始化部分
while (布尔表达式)
循环体部分
迭代部分
    当布尔表达式的值为真时,循环执行{}中的复合语句,值得注意的是,while语句格式中的初始化部分和迭代部分是任选的,可以有也可以没有。
  
dowhile语句
  do—while语句的格式为:
[初始化部分]
  do{
    循环体部分
     造代部分]
     }while(布尔表达式);[注意:] 上面的最后的条件()后面一定不要忘了加一分号 ; 。
 
    对比while语句和do—while语句可以看出,while语句首先计算终止条件,当条件满足时,才执行循环体中的语句,而do-while语句是首先执行循环体,然后计算终止条件,如果布尔
表达式的值为真,就循环执行{}中的语句,因此,while语句的循环体可能一次也没有执行,而do—while语句的循环体至少要执行一次。
 
 
For语句
for语句的一般格式为:
for (初始化部分; 终止条件部分; 迭代修正部分 )
循环体部分
    for语句执行时,首先执行初始化操作,然后判断终止条件是否满足,如果满足,则执行循环体中的语句,最后执行迭代修正部分。完成一次循环后,重新判断终止条件。
    需要注意的是,初始化、终止以及迭代部分都可以为空语句(但分号不能省),三者均为空的时候,相当于—个无限循环(通常说的死循环)。在初始化部分和迭代部分可以使用逗号语句,来进行多个操作,逗号语句是用逗号分隔的语句序列,如下面的语句所示:
for ( i=0, j=10; i <10 ; i++, j++)
{
……
}
 
 
  4  kreak语句
  在前面的switch语句中,break语句用来终止switch语句的执行,使程序从switch语句后的第一个语句开始执行。
    在Jav中,break语句的第二种使用情况就是跳出它所指定的块(作用域)并从紧跟该块的第一条语句处执行。如格式如下:
    a:{......    // 标记代码块a
    b:{......    //标记代码块b
    c:{......    //标记代码块c
    break b;
             ……  //   不会执行
              }
           …… //    不会执行
          }
        …… //   从这里开始执行
      }
    在上面的代码中,使用“break;”语句,使得程序跳出b代码块,接着执行紧跟b代码块下面的一个语句。
 
 
 
5.  continue语句
continue语句用来结束本次循环,跳过循环体中下面尚未执行的语句,接着进行终止条件的判断.以决定是否继续循环。它的格式为:
    continue;
    也可以用continue跳转到括号指明的外层循环中,这时的格式为:
    continue outerLabel;
 
 
 
6.  返回语句return
    return语句用于从当前方法中退出,返回到调用该方法的语句处,并从紧跟该语句的下一条语句继续程序的执行。return语句通常用在一个方法体的最后,否则会产生编译错误,
除非用在if-else语句中。返回语句有两种格式:
  return expression
  return
 
 
7.  异常处理语句
也括try,catch,fally,throw语句;与c/c++相比,是Java特有的语句。
 
 
 
8  注释语句
    在Java语言中,有下面三种注释方式:
    //单行注释。注释从//开始,终止于行尾。
    /* ... */ 用于多行注释。注释从/*开始,到*/结束, 且这种注释不能互相嵌套。
    /** ...*/是Java所特有的doc注释。它以/**开始,到*/结束。这种注释主要是为支持JDK
工具javadoc而采用的。javadoc能识别注释中用标记@标识的一些特殊变量,并把doc注释
加入它所生成的HTML文件。

 
 
 
 

15.    怎样定义一个类?
16.    一个类继承另外一个类?怎样调用构造函数的?

public class A {
    public A(Object obj){
        //do coding here
    }
}
public class B extends A{
    public B(Object obj){
        this.super(obj);
    }
}

 
 
 
 

17.    关于一个类的静态方法如何访问?
18.    怎样继承一个类?
19.    怎样定义一个接口?

方法一:
interface B {
    //coding here !
}
public interface A extends B{
    //coding here !
}
 
 
方法二:
abstract class C{
    public C(){
    }
}
abstract class D extends C{
    public D(){
        super();
    }
}
 
 
方法三:
public interface A {
    //coding here !
}
  
abstract class C implements A{
    public C(){
    }
}
 
 
方法四:
interface B {
    //coding here !
}
public interface A extends B{
    //coding here !
}
  
abstract class C implements A{
    public C(){
    }
}
class D extends C{
    public D(){
        super();
    }
}

 
 
 
 

20.    接口和抽象类定义有什么区别?

    接口一般用于定义业务相对稳定的功能,用接口定义的实现要求,实现者不能改变接口的参数需求和返回值类型。一旦接口的参数需求与返回值类型中的任何一项发生改变都会导致接口的失效。因此,接口带有规范的约束力。开发人员必须严格按照这种约束力来实现其功能。
 
    抽象类的要求要比接口宽松许多,因为抽象类允许对定义的业务有简单实现,因此,对于开发人员来说,不仅可以直接使用抽象类中定义的方法,而且还可以根据自身的业务需求,对抽象类中定义的方法进行重新实现。当然如果你的业务发生改变你甚至可以不去对抽象类中定义的方法进行实现。
 
    接口实现的对象,其内部行为是确定的。但是,抽象类可以用来描述对象的内部行为存在不确定性的情况。

 
 
 

21.    有关垃圾回收的概念,你能描述一下java是怎样进行垃圾收集的吗?
22.    关于finalize()方法的调用?

1.JVM的gc概述

  gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作。

  在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能。有些垃圾收集专用于特殊的应用程序。比如,实时应用程序主要是为了避免垃圾收集中断,而大多数OLTP应用程序则注重整体效率。理解了应用程序的工作负荷和jvm支持的垃圾收集算法,便可以进行优化配置垃圾收集器。

  垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。

1.1.引用计数
  引用计数存储对特定对象的所有引用数,也就是说,当应用程序创建引用以及引用超出范围时,jvm必须适当增减引用数。当某对象的引用数为0时,便可以进行垃圾收集。

1.2.对象引用遍历
  早期的jvm使用引用计数,现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,gc必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

  下一步,gc要删除不可到达的对象。删除时,有些gc只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多gc可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

  为此,gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有gc运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作,有的则采用多线程以增加效率。
2.几种垃圾回收机制

2.1.标记-清除收集器
  这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。

2.2.标记-压缩收集器
  有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。

2.3.复制收集器
  这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,jvm生成的新对象则放在另一半空间中。gc运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。

2.4.增量收集器
  增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾。这会造成较小的应用程序中断。

2.5.分代收集器
  这种收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。

2.6.并发收集器
  并发收集器与应用程序同时运行。这些收集器在某点上(比如压缩时)一般都不得不停止其他操作以完成特定的任务,但是因为其他应用程序可进行其他的后台操作,所以中断其他处理的实际时间大大降低。

2.7.并行收集器
  并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高java应用程序的可扩展性。
3.Sun HotSpot 1.4.1 JVM堆大小的调整

  Sun HotSpot 1.4.1使用分代收集器,它把堆分为三个主要的域:新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言,永久域是一个独立域并且不认为是堆的一部分。

  下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。

  下面的命令是把初始大小设置为128M:
  java –Xms128m
  –Xmx256m为控制新域的大小,可使用-XX:NewRatio设置新域在堆中所占的比例。

  下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M:
  java –Xms128m –Xmx128m
  –XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。

  下面的命令把新域的初始值和最大值设置成64m:
  java –Xms256m –Xmx256m –Xmn64m
  永久域默认大小为4m。运行程序时,jvm会调整永久域的大小以满足需要。每次调整时,jvm会对堆进行一次完全的垃圾收集。

  使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小。为了避免调整,可使用-XXerSize标志设置初始值。

  下面把永久域初始值设置成32m,最大值设置成64m。
  java -Xms512m -Xmx512m -Xmn128m -XXermSize=32m -XX:MaxPermSize=64m

  默认状态下,HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden,用于生成新的对象。另两部分称为救助空间,当Eden充满时,收集器停止应用程序,把所有可到达对象复制到当前的from救助空间,一旦当前的from救助空间充满,收集器则把可到达对象复制到当前的to救助空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制,直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可控制新域子空间的大小。

  同NewRation一样,SurvivorRation规定某救助域与Eden空间的比值。比如,以下命令把新域设置成64m,Eden占32m,每个救助域各占16m:
  java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2


如前所述,默认状态下HotSpot对新域使用复制收集器,对旧域使用标记-清除-压缩收集器。在新域中使用复制收集器有很多意义,因为应用程序生成的大部分对象是短寿命的。理想状态下,所有过渡对象在移出Eden空间时将被收集。如果能够这样的话,并且移出Eden空间的对象是长寿命的,那么理论上可以立即把它们移进旧域,避免在救助空间反复复制。但是,应用程序不能适合这种理想状态,因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象并放在新域中,因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制,可用-XX:TargetSurvivorRatio控制救助空间的比例(该值是设置救助空间的使用比例。如救助空间位1M,该值50表示可用500K)。该值是一个百分比,默认值是50。当较大的堆栈使用较低的sruvivorratio时,应增加该值到80至90,以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。

  为放置所有的复制全部发生以及希望对象从eden扩展到旧域,可以把MaxTenuring Threshold设置成0。设置完成后,实际上就不再使用救助空间了,因此应把SurvivorRatio设成最大值以最大化Eden空间,设置如下:
  java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …

4.BEA JRockit JVM的使用
  Bea WebLogic 8.1使用的新的JVM用于Intel平台。在Bea安装完毕的目录下可以看到有一个类似于jrockit81sp1_141_03的文件夹。这就是Bea新JVM所在目录。不同于HotSpot把Java字节码编译成本地码,它预先编译成类。JRockit还提供了更细致的功能用以观察JVM的运行状态,主要是独立的GUI控制台(只能适用于使用Jrockit才能使用jrockit81sp1_141_03自带的console监控一些cpu及memory参数)或者WebLogic Server控制台。

  Bea JRockit JVM支持4种垃圾收集器:
  4.1.1.分代复制收集器
  它与默认的分代收集器工作策略类似。对象在新域中分配,即JRockit文档中的nursery。这种收集器最适合单cpu机上小型堆操作。

  4.1.2.单空间并发收集器
  该收集器使用完整堆,并与背景线程共同工作。尽管这种收集器可以消除中断,但是收集器需花费较长的时间寻找死对象,而且处理应用程序时收集器经常运行。如果处理器不能应付应用程序产生的垃圾,它会中断应用程序并关闭收集。

  分代并发收集器 这种收集器在护理域使用排它复制收集器,在旧域中则使用并发收集器。由于它比单空间共同发生收集器中断频繁,因此它需要较少的内存,应用程序的运行效率也较高,注意,过小的护理域可以导致大量的临时对象被扩展到旧域中。这会造成收集器超负荷运作,甚至采用排它性工作方式完成收集。

  4.1.3.并行收集器
  该收集器也停止其他进程的工作,但使用多线程以加速收集进程。尽管它比其他的收集器易于引起长时间的中断,但一般能更好的利用内存,程序效率也较高。

  默认状态下,JRockit使用分代并发收集器。要改变收集器,可使用-Xgc:,对应四个收集器分别为gencopy,singlecon,gencon以及parallel。可使用-Xms和-Xmx设置堆的初始大小和最大值。要设置护理域,则使用-Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…尽管JRockit支持-verbose:gc开关,但它输出的信息会因收集器的不同而异。JRockit还支持memory、load和codegen的输出。

  注意 :如果 使用JRockit JVM的话还可以使用WLS自带的console(C:\bea\jrockit81sp1_141_03\bin下)来监控一些数据,如cpu,memery等。要想能构监控必须在启动服务时startWeblogic.cmd中加入-Xmanagement参数。
5.如何从JVM中获取信息来进行调整

  -verbose.gc开关可显示gc的操作内容。打开它,可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。打开-xx:+ printgcdetails开关,可以详细了解gc中的变化。打开-XX: + PrintGCTimeStamps开关,可以了解这些垃圾收集发生的时间,自jvm启动以后以秒计量。最后,通过-xx: + PrintHeapAtGC开关了解堆的更详细的信息。为了了解新域的情况,可以通过-XX:=PrintTenuringDistribution开关了解获得使用期的对象权。

6.Pdm系统JVM调整

  6.1.服务器:前提内存1G 单CPU

  可通过如下参数进行调整:-server 启用服务器模式(如果CPU多,服务器机建议使用此项)

  -Xms,-Xmx一般设为同样大小。 800m
  -Xmn 是将NewSize与MaxNewSize设为一致。320m
  -XXerSize 64m
  -XX:NewSize 320m 此值设大可调大新对象区,减少Full GC次数
  -XX:MaxNewSize 320m
  -XX:NewRato NewSize设了可不设。4
  -XX: SurvivorRatio 4
  -XX:userParNewGC 可用来设置并行收集
  -XXarallelGCThreads 可用来增加并行度 4
  -XXUseParallelGC 设置后可以使用并行清除收集器
  -XX:UseAdaptiveSizePolicy 与上面一个联合使用效果更好,利用它可以自动优化新域大小以及救助空间比值

  6.2.客户机:通过在JNLP文件中设置参数来调整客户端JVM

  JNLP中参数:initial-heap-size和max-heap-size

  这可以在framework的RequestManager中生成JNLP文件时加入上述参数,但是这些值是要求根据客户机的硬件状态变化的(如客户机的内存大小等)。建议这两个参数值设为客户机可用内存的60%(有待测试)。为了在动态生成JNLP时以上两个参数值能够随客户机不同而不同,可靠虑获得客户机系统信息并将这些嵌到首页index.jsp中作为连接请求的参数。

  在设置了上述参数后可以通过Visualgc 来观察垃圾回收的一些参数状态,再做相应的调整来改善性能。一般的标准是减少fullgc的次数,最好硬件支持使用并行垃圾回收(要求多CPU)。
 

★  Java内存管理特点
    Java一个最大的优点就是取消了指针,由垃圾收集器来自动管理内存的回收。程序员不需要通过调用函数来释放内存。

    1、Java的内存管理就是对象的分配和释放问题。
    在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。
    对象的释放是由GC决定和执行的。
    在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法简化了程序员的工作。但也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。

    GC释放空间方法:
    监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等。当该对象不再被引用时,释放对象。


    2、内存管理结构
    Java使用有向图的方式进行内存管理,对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。

    将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。

    3、使用有向图方式管理内存的优缺点
    Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。
    这种方式的优点是管理内存的精度很高,但是效率较低。

++:
另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。

★  Java的内存泄露
    Java虽然由GC来回收内存,但也是存在泄露问题的,只是比C++小一点。

    1、与C++的比较
    c++所有对象的分配和回收都需要由用户来管理。即需要管理点,也需要管理边。若存在不可达的点,无法在回收分配给那个点的内存,导致内存泄露。存在无用的对象引用,自然也会导致内存泄露。
    Java由GC来管理内存回收,GC将回收不可达的对象占用的内存空间。所以,Java需要考虑的内存泄露问题主要是那些被引用但无用的对象——即指要管理边就可以。被引用但无用的对象,程序引用了该对象,但后续不会再使用它。它占用的内存空间就浪费了。
        如果存在对象的引用,这个对象就被定义为“活动的”,同时不会被释放。

    2、Java内存泄露处理
    处理Java的内存泄露问题:确认该对象不再会被使用。
    典型的做法——
        把对象数据成员设为null
        从集合中移除该对象
    注意,当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。

例子:
List myList=new ArrayList();
for (int i=1;i<100; i++)
{
Object o=new Object();
myList.add(o);
o=null;
}
//此时,所有的Object对象都没有被释放,因为变量myList引用这些对象。

    当myList后来不再用到,将之设为null,释放所有它引用的对象。之后GC便会回收这些对象占用的内存。

★  对GC操作
    对GC的操作并不一定能达到管理内存的效果。

    GC对于程序员来说基本是透明的,不可见的。我们只有几个函数可以访问GC,例如运行GC的函数System.gc(),System.。
    但是根据Java语言规范定义, System.gc()函数不保证JVM的垃圾收集器一定会执行。因为,不同的JVM实现者可能使用不同的算法管理GC。通常,GC的线程的优先级别较低。


    JVM调用GC的策略有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。除非在一些特定的场合,GC的执行影响应用程序的性能,例如对于基于Web的实时系统,如网络游戏等,用户不希望GC突然中断应用程序执行而进行垃圾回收,那么我们需要调整GC的参数,让GC能够通过平缓的方式释放内存,例如将垃圾回收分解为一系列的小步骤执行,Sun提供的HotSpot JVM就支持这一特性。

★  内存泄露检测
    市场上已有几种专业检查Java内存泄漏的工具,它们的基本工作原理大同小异,都是通过监测Java程序运行时,所有对象的申请、释放等动作,将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。这些工具包括Optimizeit Profiler,JProbe Profiler,JinSight , Rational 公司的Purify等。

    在运行过程中,我们可以随时观察内存的使用情况,通过这种方式,我们可以很快找到那些长期不被释放,并且不再使用的对象。我们通过检查这些对象的生存周期,确认其是否为内存泄露。

 

 

 

★  软引用
    特点:只有当内存不够的时候才回收这类内存,同时又保证在Java抛出OutOfMemory异常之前,被设置为null。
          保证最大限度的使用内存而不引起OutOfMemory异常。
          在某些时候对软引用的使用会降低应用的运行效率与性能,例如:应用软引用的对象的初始化过程较为耗时,或者对象的状态在程序的运行过程中发生了变化,都会给重新创建对象与初始化对象带来不同程度的麻烦。

 

 

 

    用途:
    可以用于实现一些常用资源的缓存,实现Cache的功能
    处理一些占用内存大而且声明周期较长,但使用并不频繁的对象时应尽量应用该技术

 

 

 

★  java程序设计中有关内存管理的经验

 

 

 

1.最基本的建议是尽早释放无用对象的引用。如:
...
A a = new A();
//应用a对象
a = null; //当使用对象a之后主动将其设置为空
….
注:如果a 是方法的返回值,不要做这样的处理,否则你从该方法中得到的返回值永远为空,而且这种错误不易被发现、排除

 

 

 

2.尽量少用finalize函数。它会加大GC的工作量。
3.如果需要使用经常用到的图片,可以使用soft应用类型。它尽可能把图片保存在内存中
4.注意集合数据类型,包括数组、树、图、链表等数据结构,这些数据结构对GC来说,回收更为复杂。
5.尽量避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费
6.尽量避免强制系统做垃圾内存的回收,增长系统做垃圾回收的最终时间
7.尽量避免显式申请数组空间
8.尽量做远程方法调用类应用开发时使用瞬间值变量,除非远程调用端需要获取该瞬间值变量的值。
9.尽量在合适的场景下使用对象池技术以提高系统性能。

 

 

 

 

 


 
 
 
 
 
 
 

23.    什么叫作方法重载?
24.    完成一个类,实现将一个对象作为函数的参数传递?
25.    怎样定义一个java内部类?详细描述一下java内部类的用途,并给出一个例子?

关于内部类的使用可参看我前些日子写的一篇日志(地址如下):

 
 
 
 

26.    有关public ,protected, private ,默认类的区别
 
 
 
 
 

27.    怎样阻止一个方法被重载?

将其定义成“终态方法”

 
 
 
 
 
 

28.    java中package的意义?

Java中的包(Package)其实指的就是目录,它是为了更好地管理Java类(Class)和接口(Interface)。Java语言的包可以被另一个Java开发包所使用。关于这个问题可以参看 C++ 中的命名空间问题。

 
 
 
 
 
 

29.    列举出java中常见的几种异常?

Java中的异常分为两类,一类是 Error ,另一类是 Exception 。其中 Exception 异常通常是可控范围内的异常,但 Error 异常通常是 JVM 无法处理的异常。
可参看我的一篇日志:

 
 
 
 
 
 

30.    怎样抛出异常?试写出一个try ,catch的例子
31.    有关finally, throw ,throws 的使用,试举出例子?
32.    怎样创建一个java的多线程程序?试写出一个例子来?
33.    有关线程同步的概念?
34.    列举出常见的java.io的字节流类?试着创建一个新的file文件,并且向文件中写入字符,然后试着读出来?
 
 
 
 

35.    怎样理解instance of?

关于这个主题,可以参看我前些日子写的一篇日志(地址如下):

 
 
 
 

36.    怎样理解java关键字strictfp?

自Java2以来,Java语言增加了一个关键字strictfp,虽然这个关键字在大多数场合比较少用,但是还是有必要了解一下。
strictfp的意思是FP-strict,也就是说精确浮点的意思。在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运行环境在对浮点运算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。而一旦使用了strictfp来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。
你可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字,例如下面的代码:
1. 合法的使用关键字strictfp
strictfp inte***ce A {}
public strictfp class FpDemo1 {
strictfp void f() {}
}
2. 错误的使用方法
inte***ce A {
strictfp void f();
}
public class FpDemo2 {
strictfp FpDemo2() {}
}
一旦使用了关键字strictfp来声明某个类、接口或者方法时,那么在这个关键字所声明的范围内所有浮点运算都是精确的,符合IEEE-754规范的。例如一个类被声明为strictfp,那么该类中所有的方法都是strictfp的。

 
 
 
 
 
 

37.    关于在java中怎样使用本机方法?
38.    怎样用String方法来进行字符串处理?
39.    列举出String类中常用的方法,比如怎样创建一个字符串,怎样进行字符串连接,怎样获得一个字串,怎样从字符串中截取一个字串,怎样进行字符串比较
40.    关于equals()和==的区别?
41.    怎样获得某个字符在字符串中的索引?
42.    字符串的怎样取代某些字符,怎样trim空格?
43.    怎样用valueof方法将其他类型的数据转换为字符串?
44.    StringBuffer方法与String的区别?列举出StringBuffer中的常用方法?
45.     怎样进行字符串分割,比如将字符串用,分割?
46.    列举出java.lang中类?
47.    列举出java.lang中接口?
48.    怎样获得java中内存管理的信息?
49.    怎样调用System中的方法?
50.    怎样使用clone()和cloneable方法?
51.    描述一下Class的类?
52.    列举一下常见的Math方法?
53.    怎样使用java中反射机制?
54.    描述一下Collection , List , Set ,SortedSet接口定义和使用范围?
55.    关于ArrayList类的使用?
56.    关于LinkedList类的使用?同上有什么区别?
57.    关于HashSet类的使用?
58.    关于TreeSet类的使用?
59.    怎样通过迭代函数来访问类集?试给出一个例子?
60.    java中如何处理映射?
61.    关于HashMap类的使用?
62.    关于TreeMap类的使用?
63.    关于Arrays数组的sort方法的使用?
64.    关于Vector类的使用?
65.    关于Enumeration接口的使用?
66.    关于Stack类的使用?
67.    关于Hashtable类的使用?
68.    关于Dictionary类的使用?
69.    关于Properties类的使用?
70.    关于StringTokenizer类的使用?
71.    关于BitSet类的使用?
72.    关于java.util.Date类的使用?
73.    关于java.sql.Date类的使用?
74.    关于Calendar类的使用?
75.    关于GregorianCalendar类的使用?
76.    关于TimeZone类的使用?
77.    关于SimpleTimeZone类的使用?
78.    关于Local类的使用?
79.    关于Random类的使用?
80.    关于Observable类的使用?
81.    关于Timer和TimerTask类的使用?
82.    关于java.util.zip包?
83.    关于java.util.jar包?
84.    有关Serializable接口的使用?
85.    描述一下java.net包的结构?
86.    关于InetAddress类的使用?以及Inet4Address和Inet6Address?
87.    关于tcp/ip的套接字?怎样创建一个socket对象?
88.    关于URL类?
89.    关于URLConnection类的使用?
90.    关于tcp/ip的服务器套接字?
91.    关于DatagramPacket类的使用?
92.    关于Applet类的使用,试给出一个例子?
93.    关于getDocumentBase方法的使用?
94.    关于getAppletContext方法的使用?
95.    关于java小应用程序的事件处理?
96.    关于java.awt.event中主要事件类,请列举出常用的类?
97.    关于事件源的理解?
98.    关于事件监听器的接口?
99.    关于ActionListener接口的使用?
100.    关于AdjustmentListener接口的使用?
101.    关于ComponentListener接口的使用?
102.    关于FocusListener接口的使用?
103.    关于ItemListener接口的使用?
104.    关于WindowListener接口的使用
105.    描述一下Adapter类?
106.    描述一下Inner类?
107.    关于匿名内部类的理解?
108.    怎样使用AWT布局管理器?
109.    简要介绍一下java.awt.image包?
110.    怎样实现动画?
111.    列
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics