重新探索自我

              客觀條件受制于人,并不足懼。重要的是,我們擁有選擇的自由,可以對(duì)現(xiàn)實(shí)環(huán)境積極回應(yīng),
              為生命負(fù)責(zé),為自己創(chuàng)造有利的機(jī)會(huì),做一個(gè)“真正”操之在我的人!

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            3 隨筆 :: 10 文章 :: 5 評(píng)論 :: 0 Trackbacks

          一、概述

          對(duì)于代碼級(jí)的優(yōu)化,不管用哪種程序語(yǔ)言編程,首先都應(yīng)該注意編碼規(guī)范和風(fēng)格。不同的公司或者團(tuán)隊(duì)以至程序員個(gè)人都有自己的編碼風(fēng)格,但目的是讓程序代碼可讀、簡(jiǎn)潔、高效、易于重用。養(yǎng)成良好的編碼習(xí)慣是每個(gè)程序員的必需的。最開(kāi)始,我們可以針對(duì)自己編寫(xiě)的代碼進(jìn)行自己檢查,看看有沒(méi)有什么改進(jìn)的地方,包括注釋是否適當(dāng),命名是否恰當(dāng),程序是否最優(yōu)化等等,然后可以進(jìn)行同行評(píng)審一下,針對(duì)意見(jiàn)進(jìn)行思考,改進(jìn)自己編寫(xiě)代碼。如果公司有條件,譬如有專門(mén)的測(cè)試規(guī)范、技術(shù)配置與管理等等,可以利用他們提供的方法與工具進(jìn)行單元測(cè)試與代碼檢查。譬如用 jtest 工具,可以根據(jù)編碼規(guī)范編制一套規(guī)則,用它來(lái)檢測(cè)自己的程序是否符合規(guī)范。

          在養(yǎng)成良好的編碼習(xí)慣與編碼規(guī)范之后,我們接下來(lái)要針對(duì)程序的本身進(jìn)行優(yōu)化。首先檢查自己的代碼是不是使用的較優(yōu)的算法,在設(shè)計(jì)上是否符合邏輯,有沒(méi)有更好實(shí)現(xiàn)方式。這一點(diǎn)可能有點(diǎn)難度,隨著編程的經(jīng)驗(yàn)與思考的程度增加,會(huì)提高自己程序設(shè)計(jì)的能力。這些方面可以多看點(diǎn)這方面的書(shū),譬如《代碼大全 第二版》等等。

          最后,針對(duì)程序設(shè)計(jì)語(yǔ)言的本身特點(diǎn)進(jìn)行優(yōu)化,包括變量的創(chuàng)建、內(nèi)存的管理等等。譬如在 JAVA 中,應(yīng)該盡可能少的創(chuàng)建對(duì)象。

          另外一個(gè)方面,我們可以從大師級(jí)那里去經(jīng),閱讀大師寫(xiě)的代碼。參看一些前人的經(jīng)驗(yàn),特別是設(shè)計(jì)模式。設(shè)計(jì)模式應(yīng)該可以說(shuō)是精華的提研,但同時(shí)不要受其束縛,當(dāng)自己感覺(jué)有些不同的時(shí)候,要大膽創(chuàng)新。

          ?

          二、 Java 程序的設(shè)計(jì)風(fēng)格

          ?

          跳過(guò)閱讀,詳細(xì)風(fēng)格參見(jiàn)本目錄下的《軟件編程規(guī)范— Java.doc 》;

          如果測(cè)試部能根據(jù)編碼規(guī)范定義規(guī)則對(duì)代碼進(jìn)行單元測(cè)試,那就更好了。

          ?

          三、內(nèi)存管理

          1. 垃圾回收

          GC, Garbage Collection ,垃圾回收機(jī)制,一個(gè)對(duì)象創(chuàng)建后被放置在 JVM 的堆內(nèi)存中,

          當(dāng)永遠(yuǎn)不再引用這個(gè)對(duì)象時(shí),它將被 JVM 在堆內(nèi)存中回收。

          堆內(nèi)存( Heap ),堆內(nèi)存在 JVM 啟動(dòng)的時(shí)候被創(chuàng)建,堆內(nèi)存中存儲(chǔ)的對(duì)象可以被 JVM 自動(dòng)回收,但不能通過(guò)其他外部手段回收。 Heap 通常劃分兩個(gè)區(qū)域:新對(duì)象區(qū)域和老對(duì)象區(qū)域新對(duì)象區(qū)的對(duì)象超過(guò)生命周期,會(huì)轉(zhuǎn)入到老對(duì)象區(qū)域,并且標(biāo)記為垃圾對(duì)象,垃圾回收與對(duì)象的生命周期是緊緊聯(lián)系在一起的。

          優(yōu)化:

          1 )最好不要手動(dòng)調(diào)用 GC System.gc() ),推薦使用 obj = null 的方式來(lái)提醒 JVM 來(lái)調(diào)用 GC

          Object obj = new Object();

          ???? ?? // 使用

          obj = null ;

          ?

          2 JVM 內(nèi)存參數(shù)調(diào)整

          ???? JVM 的默認(rèn)內(nèi)存大小為 63M ,可以通過(guò) Runtime.getRuntime().maxMemory() 查看到。在硬件可行的情況下,我們可以適當(dāng)提高一下內(nèi)參數(shù),譬如對(duì)于 1G 以上的內(nèi)存,如果是服務(wù)器使用,我們可以把 newsize maxsize 設(shè)成一樣,最高達(dá)到 320M ,各參數(shù)配置如下:

          Xms, Xmx 一般設(shè)為同樣大小。 800m

          Xmn 是將 NewSize MaxNewSize 設(shè)為一致。 320m

          XX:PerSize 64m

          XX:NewSize 320m 此值設(shè)大可調(diào)大新對(duì)象區(qū),減少 Full GC 次數(shù)

          XX:MaxNewSize 320m

          XX:NewRato NewSize 設(shè)了可不設(shè)。 4

          XX: SurvivorRatio 4

          XX:userParNewGC 可用來(lái)設(shè)置并行收集

          XX:ParallelGCThreads 可用來(lái)增加并行度 4

          XXUseParallelGC 設(shè)置后可以使用并行清除收集器

          XX UseAdaptiveSizePolicy 與上面一個(gè)聯(lián)合使用效果更好,利用它可以自動(dòng)優(yōu)化新域大小以及救助空間比值

          Ps :具體性能最優(yōu)參數(shù),可以通過(guò)性能測(cè)試把參數(shù)測(cè)試出來(lái),相關(guān)性能測(cè)試方法與工具使用可以參考《 J2EE 性能測(cè)試》。

          2. JVM 的生命周期

          ?????? 我們分析期生命周期的原因在于,我們可以觀察每個(gè)階段是不是有優(yōu)化的可能性,從而進(jìn)行優(yōu)化。

          1 )創(chuàng)建階段:分配存儲(chǔ)空間 -- > 構(gòu)造對(duì)象 -- > 遞歸調(diào)用超類構(gòu)造函數(shù) -- > 象實(shí)例初始化與變量的初始化 -- > 行構(gòu)造方法體

          優(yōu)化:

          根據(jù)對(duì)象創(chuàng)建的應(yīng)用規(guī)則進(jìn)行優(yōu)化:

          a.?????? 避免在循環(huán)體內(nèi)創(chuàng)建對(duì)象,即使該對(duì)象占用的內(nèi)存空間不大,應(yīng)該采用如下方式

          Object obj = null;

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

          obj = new Object();

          ?… …

          }

          b.?????? 不要一個(gè)對(duì)象初始化多次

          Object obj = new Object();

          // 這樣寫(xiě)不正確,應(yīng)該聲明為空,在使用的時(shí)候再創(chuàng)建實(shí)例

          // 正確寫(xiě)法 Object obj = null;

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

          }

          c.?????? 盡量及時(shí)使對(duì)象符合垃圾回收的標(biāo)準(zhǔn)

          譬如使用 obi = null;

          或者調(diào)用規(guī)則的方法,如 servlet destroy() 方法。

          d.?????? 不要采用過(guò)深的繼承層次

          因?yàn)槔^承類的初始化會(huì)調(diào)用基類的默認(rèn)構(gòu)造函數(shù),導(dǎo)致大量的開(kāi)銷。一般繼承

          結(jié)構(gòu)不宜超過(guò) 3 層,另外,推薦使用接口。

          e.?????? 訪問(wèn)本地變量?jī)?yōu)于訪問(wèn)類中的變量

          譬如 String 對(duì)象類型,如果使用 String.length() 方法超過(guò)兩次,我們應(yīng)該考慮

          使用一個(gè)變量來(lái)替代, int temp = String.length();

          2 )應(yīng)用階段:

          ?????? 在應(yīng)用階段,系統(tǒng)至少維護(hù)著對(duì)象的強(qiáng)引用。

          ?????? 強(qiáng)應(yīng)用( Strong Reference ):指 JVM 內(nèi)存管理器從根引用集合( Root Set )出發(fā)遍尋堆中所有到達(dá)對(duì)象的路徑。

          軟應(yīng)用( Soft Reference ):具有較強(qiáng)的引用功能。可以用于實(shí)現(xiàn)一些常用的資源的緩存,實(shí)現(xiàn) Cache 的功能,保證最大限度的使用內(nèi)存而不引起 Out Of Memory 。軟引用技術(shù)的引進(jìn)使 Java 應(yīng)用可以更好的管理內(nèi)存,穩(wěn)定系統(tǒng),防止系統(tǒng)內(nèi)存溢出。軟引用使用方式:

          A a = new A();

          ……

          // 使用完 a ,將它設(shè)置為 soft 引用類型,并且釋放強(qiáng)引用 ;

          SoftReference sr = new SoftReference(a);

          a = null;

          ??????

          // 下次使用

          if( sr != null) {

          ?????? a = sr.get();

          }else{

          ?????? //GC 由于低內(nèi)存,已釋放 a ,因此需要重新裝載

          ?????? a = new A();

          ??? sr = new SoftRerence(a);

          }

          弱引用( Weak Reference ):與 soft 引用對(duì)象不同之處在于: GC 在進(jìn)行回收時(shí),需要通過(guò)算法檢查是否回收 Soft 引用對(duì)象,而對(duì)于 Weak 對(duì)象, GC 總是進(jìn)行回收。

          虛引用( Phantom Reference ):輔助 finalize 函數(shù)的使用。

          3 )其他階段

          不可視階段

          不可到達(dá)階段

          可收集階段、終結(jié)階段與釋放階段,

          ?

          3. 構(gòu)造函數(shù)與 Finalize 函數(shù)

          構(gòu)造函數(shù)會(huì)在類初始化實(shí)例的時(shí)候?qū)?huì)被執(zhí)行,因此,我們?cè)谠O(shè)計(jì)類的時(shí)候盡可能的避免在類的默認(rèn)構(gòu)造函數(shù)中創(chuàng)建、初始化大量的對(duì)象。

          finalize ,類似 C++ 中析構(gòu)函數(shù)

          ?

          4. 數(shù)組的創(chuàng)建

          創(chuàng)建的時(shí)候,一般我們盡可能的使用隱式創(chuàng)建:

          int [] intArray = obj.getIntArray();

          如果碰到占用內(nèi)存空間比較大的時(shí)候,我們通過(guò)軟引用技術(shù)來(lái)應(yīng)用數(shù)組。

          ?

          5. 共享靜態(tài)變量存儲(chǔ)空間

          靜態(tài)變量可以節(jié)約大量的內(nèi)存開(kāi)銷,使用情況:

          (1)?????? 變量做所包含的對(duì)象體積較大,占用內(nèi)存較多

          (2)?????? 變量所包含的對(duì)象生命周期長(zhǎng)

          (3)?????? 變量所包含的數(shù)據(jù)穩(wěn)定

          (4)?????? 該類的對(duì)象實(shí)例有對(duì)該變量所包含對(duì)象的共享需求

          ?

          ?

          6. 對(duì)象重用

          緩存對(duì)象的應(yīng)用,對(duì)象池( ObjectPool , 通過(guò)對(duì)其所保存對(duì)象的共享和重用,縮減了應(yīng)用線程反復(fù)重建、裝載對(duì)象所需要的時(shí)間,并且避免頻繁的垃圾回收帶來(lái)的巨大開(kāi)銷。

          譬如數(shù)據(jù)庫(kù)的連接池,對(duì)一個(gè)數(shù)據(jù)庫(kù)連接池詳細(xì)研究

          參見(jiàn)文章《數(shù)據(jù)庫(kù)連接池技術(shù)》

          7. 瞬間值

          實(shí)現(xiàn) Java.lang.Serializable 接口,具體使用參見(jiàn)其 API

          8.Java 程序設(shè)計(jì)其他經(jīng)驗(yàn)

          (1) 盡早釋放無(wú)用引用對(duì)象, obj = null ;

          (2) 盡量少用 finalize 函數(shù)

          (3) 如果經(jīng)常使用圖片,可以使用 soft 應(yīng)用類型

          (4) 注意集合數(shù)據(jù)類型,這些對(duì) GC 來(lái)說(shuō),回收更復(fù)雜

          ?? 注意一些全局變量,或者靜態(tài)變量容易引起懸掛對(duì)象,造成對(duì)象浪費(fèi)

          (5) 盡量避免在類的默認(rèn)構(gòu)造器中創(chuàng)建、初始化大量的對(duì)象

          (6) 盡量避免強(qiáng)制系統(tǒng)調(diào)用 GC System.gc()

          (7) 盡量避免顯式申請(qǐng)數(shù)組空間

          (8) 盡量在做 RMI 類應(yīng)用開(kāi)發(fā)時(shí)使用瞬間值( transient )變量

          (9) 盡量在合適的場(chǎng)合下使用對(duì)象池技術(shù)以提高系統(tǒng)性能


          參考資料:
          ?《Java優(yōu)化編程》?

          posted on 2006-09-05 15:33 蔣利文 閱讀(420) 評(píng)論(1)  編輯  收藏 所屬分類: 技術(shù)總結(jié)

          評(píng)論

          # re: JAVA優(yōu)化編程_Part1 2006-09-05 15:36 蔣利文
          優(yōu)化是永恒的主題,學(xué)習(xí)中,修煉程序員的內(nèi)容!
          《Java優(yōu)化編程》繼續(xù)學(xué)習(xí)中,待續(xù)...
          有機(jī)會(huì)在研究一下《JVM虛擬機(jī)》  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 甘谷县| 苍南县| 三门峡市| 祁东县| 岳阳市| 兴安县| 安吉县| 蛟河市| 雷山县| 新化县| 厦门市| 高台县| 屏南县| 临桂县| 潞西市| 彩票| 都昌县| 利辛县| 兴山县| 义乌市| 金华市| 巴林右旗| 微山县| 安远县| 乌拉特中旗| 黔西| 手游| 潢川县| 江源县| 前郭尔| 三亚市| 嫩江县| 富宁县| 孝昌县| 横山县| 通辽市| 东兴市| 彰化县| 彰武县| 广州市| 凭祥市|