• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

      Java內(nèi)存不足PermGen space錯(cuò)誤探究

      2012-04-29 07:00:52錢宇虹
      軟件工程 2012年11期
      關(guān)鍵詞:字節(jié)應(yīng)用程序內(nèi)存

      錢宇虹

      摘要:Java程序運(yùn)行時(shí)可能會(huì)遇到j(luò)ava.lang.OutOfMemoryError: PermGen space錯(cuò)誤;JavaEE服務(wù)器(如tomcat、jboss等)在加載war包或ear包時(shí)也可能會(huì)出現(xiàn)這種錯(cuò)誤,這些都是由于永久保存區(qū)域內(nèi)存不足導(dǎo)致的。本文分析了Java程序的運(yùn)行機(jī)制和JVM的內(nèi)存結(jié)構(gòu),解釋了什么是permanent generation space,分析了PermGen space錯(cuò)誤的常見(jiàn)原因,并給出避免這一錯(cuò)誤的解決辦法。

      關(guān)鍵詞:JVM; 類加載器; OutOfMemoryError:PermGen space

      Java 程序的運(yùn)行機(jī)制與普通程序,如C或C++ 程序的運(yùn)行機(jī)制有很大的區(qū)別。

      普通程序運(yùn)行之前必須首先編譯成可執(zhí)行的二進(jìn)制碼或機(jī)器碼。機(jī)器碼是與底層的硬件結(jié)構(gòu)相關(guān)的,即使書寫源代碼的時(shí)候沒(méi)有利用平臺(tái)特定的擴(kuò)展語(yǔ)言,如特定的文件訪問(wèn)或圖形用戶界面,生成的機(jī)器碼仍然被綁定到一個(gè)特定的硬件平臺(tái),從而只能運(yùn)行在那個(gè)體系結(jié)構(gòu)上,也就是說(shuō),為Sun工作站編譯的機(jī)器碼不能運(yùn)行在PC機(jī)上,為PC機(jī)編譯的機(jī)器碼不能運(yùn)行在蘋果機(jī)上,以此類推。

      與此相反,Java源代碼不是為某種特定平臺(tái)編譯的,而是編譯成與平臺(tái)無(wú)關(guān)的字節(jié)碼(Byte Code),這種字節(jié)碼叫做Java Class(Java 類文件) 。在任何一種操作系統(tǒng)平臺(tái)上的字節(jié)碼都是一樣的,因此都可以在任何支持Java 虛擬機(jī)(JVM)的計(jì)算機(jī)上運(yùn)行。JVM 直接受操作系統(tǒng)控制(而不是Java程序直接受操作系統(tǒng)控制),它負(fù)責(zé)將字節(jié)碼轉(zhuǎn)換成在特定平臺(tái)上能夠運(yùn)行的機(jī)器碼。正是由于這個(gè)原因,Java做到了“write once, run anywhere”(書寫一次,到處運(yùn)行)[1]。

      運(yùn)行Java程序時(shí),首先需要由JVM把Java class加載到JVM里面。通常情況下,我們不會(huì)去關(guān)注JVM的內(nèi)部工作細(xì)節(jié)而只是直接拿來(lái)使用。然而,作為一個(gè)Java開(kāi)發(fā)人員,你經(jīng)常會(huì)遇到與內(nèi)存相關(guān)的性能問(wèn)題。這個(gè)問(wèn)題最可怕的就是OutOfMemoryError:PermGen space錯(cuò)誤。

      這個(gè)錯(cuò)誤通常會(huì)在以下三種情況下發(fā)生(服務(wù)器以Tomcat為例):

      (1)應(yīng)用程序加載了大量的類。

      (2)在單一的Tomcat實(shí)例下運(yùn)行多個(gè)Web應(yīng)用程序。

      (3)在運(yùn)行的Tomcat實(shí)例中反復(fù)“熱部署”Web應(yīng)用程序。

      下面我們對(duì)該錯(cuò)誤進(jìn)行探究,分析該錯(cuò)誤的常見(jiàn)原因,并給出避免這一錯(cuò)誤的解決辦法。

      1.JVM 的內(nèi)存結(jié)構(gòu)

      為了理解這一錯(cuò)誤,我們必須了解JVM的內(nèi)存是如何構(gòu)造的。

      JVM有兩個(gè)內(nèi)存區(qū)域,一個(gè)是堆(heap),另一個(gè)是棧(stack)。局部的變量和方法駐留在棧里面,其余的一切都駐留在堆中。

      Java的堆又進(jìn)一步按照區(qū)域進(jìn)行組織,這些區(qū)域被稱為generation。一個(gè)對(duì)象在JVM存在的時(shí)間越長(zhǎng),它被升遷到老的generation中的幾率就越高。年輕的generation要比老的generation更多地被垃圾回收。同時(shí)還存在一些單獨(dú)的堆空間,被稱為永久保存區(qū)域(permanent generation),它們不屬于Java堆的一部分,用來(lái)存放類和類的描述。

      類加載器的工作是不斷地部署和取消部署Java類。例如,將一個(gè)Web應(yīng)用程序部署到Web服務(wù)器或取消部署。在Web服務(wù)器上,所有應(yīng)用程序都有自己的類加載器,部署或取消部署應(yīng)用程序時(shí),它的類定義和類加載器分別投入到永久保存區(qū)域中或者從永久保存區(qū)域中刪除。

      2.OutOfMemoryError: PermGen space

      當(dāng)永久保存區(qū)域的空間耗盡時(shí)OutOfMemoryError: PermGen space就會(huì)發(fā)生,這個(gè)錯(cuò)誤一般是由于內(nèi)存泄漏導(dǎo)致的。所謂內(nèi)存泄漏,是指java類和類加載器在被取消部署后不能被垃圾回收[2]。怎么會(huì)發(fā)生這種情況呢?舉個(gè)例子:假如我們有一個(gè)Student類,這個(gè)類是Web應(yīng)用程序jar包的一部分,同時(shí)在Web服務(wù)器的lib文件夾中包含了某種日志框架,其中有一個(gè)Log類提供register方法調(diào)用,從而使得別的類通過(guò)注冊(cè)就可以使用日志功能。如果Student類被注冊(cè)了,那么Log類就開(kāi)始擁有了一個(gè)對(duì)Student對(duì)象的引用(reference)。當(dāng)Student類取消部署時(shí),它仍然是注冊(cè)Log類的,Log類仍然擁有對(duì)Student對(duì)象的引用,因此,Student對(duì)象永遠(yuǎn)不會(huì)被垃圾回收。此外,由于Student對(duì)象擁有一個(gè)對(duì)它的ClassLoader的引用,所以ClassLoader本身永遠(yuǎn)也不會(huì)被垃圾回收,從而導(dǎo)致由它加載的所有類都不會(huì)被回收。

      一個(gè)更為典型的例子是使用代理對(duì)象。Spring和Hibernate常常為某些類生成代理類,這些代理類也是通過(guò)類加載器加載的,并且存儲(chǔ)在永久保存區(qū)域的堆空間,它們永遠(yuǎn)不會(huì)被丟棄,從而會(huì)導(dǎo)致永久保存區(qū)域的堆空間被填滿。

      3.如何避免永久保存區(qū)域內(nèi)存不足

      3.1 增加PermGen堆的最大尺寸

      當(dāng)遇到j(luò)ava.lang.OutOfMemoryError:PermGen space錯(cuò)誤時(shí),我們可以做的第一件事情是增加永久保存區(qū)域的最大尺寸,該尺寸的缺省設(shè)置是64 M,我們可以將它設(shè)置成128 M以上。這個(gè)工作不能通過(guò)常規(guī)的JVM參數(shù) -Xms(設(shè)置初始堆大小)和-Xmx(設(shè)置最大堆大?。﹣?lái)完成,因?yàn)榍懊嬉呀?jīng)提到,永久保存區(qū)域完全獨(dú)立于普通的Java堆,這些參數(shù)是用來(lái)設(shè)置普通的Java堆的。不過(guò)也有類似參數(shù)用于設(shè)置永久保存區(qū)域的規(guī)模:

      java-XX:MaxPermSize=128 M

      該設(shè)置將永久保存區(qū)域設(shè)置為128 M,這個(gè)大小是默認(rèn)設(shè)置的兩倍。

      對(duì)于Tomcat服務(wù)器,則需要修改TOMCAT_HOME/bin/catalina.sh

      SET JAVA_OPTS=-XX:PermSize=64 M -XX:MaxPermSize=128 M [3]

      3.2 避免使用靜態(tài)字段

      確保在編寫Java類時(shí),不要使用靜態(tài)變量作為對(duì)其他對(duì)象的引用。

      3.3使用JDK動(dòng)態(tài)代理,而不是CGLIB代理

      一些第三方的框架,如CGLIB會(huì)吞食大量的PermGen。因此,當(dāng)遇到PermGen錯(cuò)誤時(shí),應(yīng)盡快升級(jí)cglib到最新版;改用JDK動(dòng)態(tài)代理,也是一個(gè)不錯(cuò)的選擇。

      3.4更新到最新版本Hibernate3.2

      此外,新版本的Hibernate不再使用CGLIB作為字節(jié)碼提供者了,所以及時(shí)升級(jí)Hibernate,會(huì)大大降低出錯(cuò)的機(jī)會(huì)。

      3.5共用的jar文件放到共享目錄下

      如果在服務(wù)器上同時(shí)發(fā)布了多個(gè)應(yīng)用,那么應(yīng)該把共用的jar文件放到所有應(yīng)用都可以訪問(wèn)的目錄下。針對(duì)Tomcat而言,如果Tomcat下面有多個(gè)應(yīng)用,應(yīng)盡可能地把lib目錄下共用的jar文件放到Tomcat的common\lib或shared\lib下,以避免重復(fù)發(fā)布,發(fā)布速度和運(yùn)行速度上也會(huì)有所提升。

      4.結(jié)束語(yǔ)

      內(nèi)存不足問(wèn)題是潛伏較深的問(wèn)題,且不容易解決。一般情況下,當(dāng)發(fā)生該錯(cuò)誤的時(shí)候,需要確定為什么某些類不被垃圾回收,只有這樣做才能夠消除這個(gè)錯(cuò)誤。

      參考文獻(xiàn)

      [1] Jacquie Barker.Beginning Java Objects From Concept to Code[M] . Birmingham, UK. Published by Wrox Press Ltd.,2000.

      [2]Oracle Docs, Chapter 3, Troubleshooting Memory Leaks,

      http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/memleaks.html.

      [3] Eric Simmerman,Preventing Java's java.lang.OutOfMemoryError: PermGen space failure [EB],2006.

      猜你喜歡
      字節(jié)應(yīng)用程序內(nèi)存
      No.8 字節(jié)跳動(dòng)將推出獨(dú)立出口電商APP
      刪除Win10中自帶的應(yīng)用程序
      “春夏秋冬”的內(nèi)存
      No.10 “字節(jié)跳動(dòng)手機(jī)”要來(lái)了?
      簡(jiǎn)談MC7字節(jié)碼
      基于內(nèi)存的地理信息訪問(wèn)技術(shù)
      關(guān)閉應(yīng)用程序更新提醒
      電腦迷(2012年15期)2012-04-29 17:09:47
      人類進(jìn)入“澤它時(shí)代”
      三星電子將開(kāi)設(shè)應(yīng)用程序下載商店
      微軟軟件商店開(kāi)始接受應(yīng)用程序
      江油市| 乐亭县| 蛟河市| 金乡县| 祁阳县| 来宾市| 册亨县| 安西县| 陇西县| 济南市| 曲麻莱县| 乳山市| 香港 | 桑植县| 鸡泽县| 张家界市| 海阳市| 广安市| 包头市| 漳平市| 喀什市| 探索| 长岭县| 仙游县| 资源县| 保德县| 宜兴市| 泗水县| 凤台县| 丰城市| 景德镇市| 鄂伦春自治旗| 婺源县| 平和县| 巴东县| 新闻| 肃宁县| 平安县| 永宁县| 濮阳县| 乡城县|