重新探索自我

    客观条件受制于人,并不足惧。重要的是,我们拥有选择的自由,可以对现实环境积极回应,
    为生命负责,为自己创造有利的机会,做一个“真正”操之在我的人!

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  3 随笔 :: 10 文章 :: 5 评论 :: 0 Trackbacks

一、概述

对于代码级的优化,不管用哪种程序语言编程,首先都应该注意编码规范和风格。不同的公司或者团队以至程序员个人都有自己的编码风格,但目的是让程序代码可读、简洁、高效、易于重用。养成良好的编码习惯是每个程序员的必需的。最开始,我们可以针对自己编写的代码进行自己检查,看看有没有什么改进的地方,包括注释是否适当,命名是否恰当,程序是否最优化等等,然后可以进行同行评审一下,针对意见进行思考,改进自己编写代码。如果公司有条件,譬如有专门的测试规范、技术配置与管理等等,可以利用他们提供的方法与工具进行单元测试与代码检查。譬如用 jtest 工具,可以根据编码规范编制一套规则,用它来检测自己的程序是否符合规范。

在养成良好的编码习惯与编码规范之后,我们接下来要针对程序的本身进行优化。首先检查自己的代码是不是使用的较优的算法,在设计上是否符合逻辑,有没有更好实现方式。这一点可能有点难度,随着编程的经验与思考的程度增加,会提高自己程序设计的能力。这些方面可以多看点这方面的书,譬如《代码大全 第二版》等等。

最后,针对程序设计语言的本身特点进行优化,包括变量的创建、内存的管理等等。譬如在 JAVA 中,应该尽可能少的创建对象。

另外一个方面,我们可以从大师级那里去经,阅读大师写的代码。参看一些前人的经验,特别是设计模式。设计模式应该可以说是精华的提研,但同时不要受其束缚,当自己感觉有些不同的时候,要大胆创新。

 

二、 Java 程序的设计风格

 

跳过阅读,详细风格参见本目录下的《软件编程规范— Java.doc 》;

如果测试部能根据编码规范定义规则对代码进行单元测试,那就更好了。

 

三、内存管理

1. 垃圾回收

GC, Garbage Collection ,垃圾回收机制,一个对象创建后被放置在 JVM 的堆内存中,

当永远不再引用这个对象时,它将被 JVM 在堆内存中回收。

堆内存( Heap ),堆内存在 JVM 启动的时候被创建,堆内存中存储的对象可以被 JVM 自动回收,但不能通过其他外部手段回收。 Heap 通常划分两个区域:新对象区域和老对象区域新对象区的对象超过生命周期,会转入到老对象区域,并且标记为垃圾对象,垃圾回收与对象的生命周期是紧紧联系在一起的。

优化:

1 )最好不要手动调用 GC System.gc() ),推荐使用 obj = null 的方式来提醒 JVM 来调用 GC

Object obj = new Object();

        // 使用

obj = null ;

 

2 JVM 内存参数调整

     JVM 的默认内存大小为 63M ,可以通过 Runtime.getRuntime().maxMemory() 查看到。在硬件可行的情况下,我们可以适当提高一下内参数,譬如对于 1G 以上的内存,如果是服务器使用,我们可以把 newsize maxsize 设成一样,最高达到 320M ,各参数配置如下:

Xms, Xmx 一般设为同样大小。 800m

Xmn 是将 NewSize MaxNewSize 设为一致。 320m

XX:PerSize 64m

XX:NewSize 320m 此值设大可调大新对象区,减少 Full GC 次数

XX:MaxNewSize 320m

XX:NewRato NewSize 设了可不设。 4

XX: SurvivorRatio 4

XX:userParNewGC 可用来设置并行收集

XX:ParallelGCThreads 可用来增加并行度 4

XXUseParallelGC 设置后可以使用并行清除收集器

XX UseAdaptiveSizePolicy 与上面一个联合使用效果更好,利用它可以自动优化新域大小以及救助空间比值

Ps :具体性能最优参数,可以通过性能测试把参数测试出来,相关性能测试方法与工具使用可以参考《 J2EE 性能测试》。

2. JVM 的生命周期

       我们分析期生命周期的原因在于,我们可以观察每个阶段是不是有优化的可能性,从而进行优化。

1 )创建阶段:分配存储空间 -- > 构造对象 -- > 递归调用超类构造函数 -- > 象实例初始化与变量的初始化 -- > 行构造方法体

优化:

根据对象创建的应用规则进行优化:

a.       避免在循环体内创建对象,即使该对象占用的内存空间不大,应该采用如下方式

Object obj = null;

for( int i=0 ; i<1000 ; ++i ) {

obj = new Object();

 … …

}

b.       不要一个对象初始化多次

Object obj = new Object();

// 这样写不正确,应该声明为空,在使用的时候再创建实例

// 正确写法 Object obj = null;

if ( … ) {
         obi = new Object();

}

c.       尽量及时使对象符合垃圾回收的标准

譬如使用 obi = null;

或者调用规则的方法,如 servlet destroy() 方法。

d.       不要采用过深的继承层次

因为继承类的初始化会调用基类的默认构造函数,导致大量的开销。一般继承

结构不宜超过 3 层,另外,推荐使用接口。

e.       访问本地变量优于访问类中的变量

譬如 String 对象类型,如果使用 String.length() 方法超过两次,我们应该考虑

使用一个变量来替代, int temp = String.length();

2 )应用阶段:

       在应用阶段,系统至少维护着对象的强引用。

       强应用( Strong Reference ):指 JVM 内存管理器从根引用集合( Root Set )出发遍寻堆中所有到达对象的路径。

软应用( Soft Reference ):具有较强的引用功能。可以用于实现一些常用的资源的缓存,实现 Cache 的功能,保证最大限度的使用内存而不引起 Out Of Memory 。软引用技术的引进使 Java 应用可以更好的管理内存,稳定系统,防止系统内存溢出。软引用使用方式:

A a = new A();

……

// 使用完 a ,将它设置为 soft 引用类型,并且释放强引用 ;

SoftReference sr = new SoftReference(a);

a = null;

      

// 下次使用

if( sr != null) {

       a = sr.get();

}else{

       //GC 由于低内存,已释放 a ,因此需要重新装载

       a = new A();

    sr = new SoftRerence(a);

}

弱引用( Weak Reference ):与 soft 引用对象不同之处在于: GC 在进行回收时,需要通过算法检查是否回收 Soft 引用对象,而对于 Weak 对象, GC 总是进行回收。

虚引用( Phantom Reference ):辅助 finalize 函数的使用。

3 )其他阶段

不可视阶段

不可到达阶段

可收集阶段、终结阶段与释放阶段,

 

3. 构造函数与 Finalize 函数

构造函数会在类初始化实例的时候将会被执行,因此,我们在设计类的时候尽可能的避免在类的默认构造函数中创建、初始化大量的对象。

finalize ,类似 C++ 中析构函数

 

4. 数组的创建

创建的时候,一般我们尽可能的使用隐式创建:

int [] intArray = obj.getIntArray();

如果碰到占用内存空间比较大的时候,我们通过软引用技术来应用数组。

 

5. 共享静态变量存储空间

静态变量可以节约大量的内存开销,使用情况:

(1)       变量做所包含的对象体积较大,占用内存较多

(2)       变量所包含的对象生命周期长

(3)       变量所包含的数据稳定

(4)       该类的对象实例有对该变量所包含对象的共享需求

 

 

6. 对象重用

缓存对象的应用,对象池( ObjectPool , 通过对其所保存对象的共享和重用,缩减了应用线程反复重建、装载对象所需要的时间,并且避免频繁的垃圾回收带来的巨大开销。

譬如数据库的连接池,对一个数据库连接池详细研究

参见文章《数据库连接池技术》

7. 瞬间值

实现 Java.lang.Serializable 接口,具体使用参见其 API

8.Java 程序设计其他经验

(1) 尽早释放无用引用对象, obj = null ;

(2) 尽量少用 finalize 函数

(3) 如果经常使用图片,可以使用 soft 应用类型

(4) 注意集合数据类型,这些对 GC 来说,回收更复杂

   注意一些全局变量,或者静态变量容易引起悬挂对象,造成对象浪费

(5) 尽量避免在类的默认构造器中创建、初始化大量的对象

(6) 尽量避免强制系统调用 GC System.gc()

(7) 尽量避免显式申请数组空间

(8) 尽量在做 RMI 类应用开发时使用瞬间值( transient )变量

(9) 尽量在合适的场合下使用对象池技术以提高系统性能


参考资料:
 《Java优化编程》 

posted on 2006-09-05 15:33 蒋利文 阅读(397) 评论(1)  编辑  收藏 所属分类: 技术总结

评论

# re: JAVA优化编程_Part1 2006-09-05 15:36 蒋利文
优化是永恒的主题,学习中,修炼程序员的内容!
《Java优化编程》继续学习中,待续...
有机会在研究一下《JVM虚拟机》  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: