日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java内存不足之PermGen space错误探究

發(fā)布時間:2025/3/16 java 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内存不足之PermGen space错误探究 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

 一.Java 程序的運行機制與普通程序,如C或C++ 程序的運行機制有很大的區(qū)別。
  普通程序運行之前必須首先編譯成可執(zhí)行的二進制碼或機器碼。機器碼是與底層的硬件結(jié)構(gòu)相關(guān)的,即使書寫源代碼的時候沒有利用平臺特定的擴展語言,如特定的文件訪問或圖形用戶界面,生成的機器碼仍然被綁定到一個特定的硬件平臺,從而只能運行在那個體系結(jié)構(gòu)上,也就是說,為Sun工作站編譯的機器碼不能運行在PC機上,為PC機編譯的機器碼不能運行在蘋果機上,以此類推。
  與此相反,Java源代碼不是為某種特定平臺編譯的,而是編譯成與平臺無關(guān)的字節(jié)碼(Byte Code),這種字節(jié)碼叫做Java Class(Java 類文件)。在任何一種操作系統(tǒng)平臺上的字節(jié)碼都是一樣的,因此都可以在任何支持Java 虛擬機(JVM)的計算機上運行。JVM 直接受操作系統(tǒng)控制(而不是Java程序直接受操作系統(tǒng)控制),它負責將字節(jié)碼轉(zhuǎn)換成在特定平臺上能夠運行的機器碼。正是由于這個原因,Java做到了“write once, run anywhere”(書寫一次,到處運行)
  運行Java程序時,首先需要由JVM把Java class加載到JVM里面。通常情況下,我們不會去關(guān)注JVM的內(nèi)部工作細節(jié)而只是直接拿來使用。然而,作為一個Java開發(fā)人員,你經(jīng)常會遇到與內(nèi)存相關(guān)的性能問題。這個問題最可怕的就是OutOfMemoryError:PermGen space錯誤。
  這個錯誤通常會在以下三種情況下發(fā)生(服務(wù)器以Tomcat為例):
  (1)應用程序加載了大量的類。
  (2)在單一的Tomcat實例下運行多個Web應用程序。
  (3)在運行的Tomcat實例中反復“熱部署”Web應用程序。
  下面我們對該錯誤進行探究,分析該錯誤的常見原因,并給出避免這一錯誤的解決辦法。
  1.JVM 的內(nèi)存結(jié)構(gòu)
  為了理解這一錯誤,我們必須了解JVM的內(nèi)存是如何構(gòu)造的。
  JVM有兩個內(nèi)存區(qū)域,一個是堆(heap),另一個是棧(stack)。局部的變量和方法駐留在棧里面,其余的一切都駐留在堆中。
  Java的堆又進一步按照區(qū)域進行組織,這些區(qū)域被稱為generation。一個對象在JVM存在的時間越長,它被升遷到老的generation中的幾率就越高。年輕的generation要比老的generation更多、更容易地被垃圾回收。同時還存在一些單獨的堆空間,被稱為永久保存區(qū)域(permanent generation),它們不屬于Java堆的一部分,用來存放類和類的描述。
  類加載器的工作是不斷地部署和取消部署Java類。例如,將一個Web應用程序部署到Web服務(wù)器或取消部署。在Web服務(wù)器上,所有應用程序都有自己的類加載器,部署或取消部署應用程序時,它的類定義和類加載器分別投入到永久保存區(qū)域中或者從永久保存區(qū)域中刪除。
  2.OutOfMemoryError: PermGen space
  當永久保存區(qū)域的空間耗盡時OutOfMemoryError: PermGen space就會發(fā)生,這個錯誤一般是由于內(nèi)存泄漏導致的。所謂內(nèi)存泄漏,是指java類和類加載器在被取消部署后不能被垃圾回收。怎么會發(fā)生這種情況呢?舉個例子:假如我們有一個Student類,這個類是Web應用程序jar包的一部分,同時在Web服務(wù)器的lib文件夾中包含了某種日志框架,其中有一個Log類提供register方法調(diào)用,從而使得別的類通過注冊就可以使用日志功能。如果Student類被注冊了,那么Log類就開始擁有了一個對Student對象的引用(reference)。當Student類取消部署時,它仍然是注冊Log類的,Log類仍然擁有對Student對象的引用,因此,Student對象永遠不會被垃圾回收。此外,由于Student對象擁有一個對它的ClassLoader的引用,所以ClassLoader本身永遠也不會被垃圾回收,從而導致由它加載的所有類都不會被回收。
  一個更為典型的例子是使用代理對象。Spring和Hibernate常常為某些類生成代理類,這些代理類也是通過類加載器加載的,并且存儲在永久保存區(qū)域的堆空間,它們永遠不會被丟棄,從而會導致永久保存區(qū)域的堆空間被填滿。
  3.如何避免永久保存區(qū)域內(nèi)存不足
  3.1 增加PermGen堆的最大尺寸
  當遇到j(luò)ava.lang.OutOfMemoryError:PermGen space錯誤時,我們可以做的第一件事情是增加永久保存區(qū)域的最大尺寸,該尺寸的缺省設(shè)置是64 M,我們可以將它設(shè)置成128 M以上。這個工作不能通過常規(guī)的JVM參數(shù) -Xms(設(shè)置初始堆大小)和-Xmx(設(shè)置最大堆大小)來完成,因為前面已經(jīng)提到,永久保存區(qū)域完全獨立于普通的Java堆,這些參數(shù)是用來設(shè)置普通的Java堆的。不過也有類似參數(shù)用于設(shè)置永久保存區(qū)域的規(guī)模:
  java -XX:MaxPermSize=128 M
  該設(shè)置將永久保存區(qū)域設(shè)置為128 M,這個大小是默認設(shè)置的兩倍。
  對于Tomcat服務(wù)器,則需要修改TOMCAT_HOME/bin/catalina.sh
  SET JAVA_OPTS=-XX:PermSize=64 M -XX:MaxPermSize=128 M?
  3.2 避免使用靜態(tài)字段
  確保在編寫Java類時,不要使用靜態(tài)變量作為對其他對象的引用。
  3.3使用JDK動態(tài)代理,而不是CGLIB代理
  一些第三方的框架,如CGLIB會吞食大量的PermGen。因此,當遇到PermGen錯誤時,應盡快升級cglib到最新版;改用JDK動態(tài)代理,也是一個不錯的選擇。
  3.4更新到最新版本Hibernate3.2
  此外,新版本的Hibernate不再使用CGLIB作為字節(jié)碼提供者了,所以及時升級Hibernate,會大大降低出錯的機會。
  3.5共用的jar文件放到共享目錄下
  如果在服務(wù)器上同時發(fā)布了多個應用,那么應該把共用的jar文件放到所有應用都可以訪問的目錄下。針對Tomcat而言,如果Tomcat下面有多個應用,應盡可能地把lib目錄下共用的jar文件放到Tomcat的common\lib或shared\lib下,以避免重復發(fā)布,發(fā)布速度和運行速度上也會有所提升。
  4.結(jié)束語
  內(nèi)存不足問題是潛伏較深的問題,且不容易解決。一般情況下,當發(fā)生該錯誤的時候,需要確定為什么某些類不被垃圾回收,只有這樣做才能夠消除這個錯誤。
  

本文摘自中國論文網(wǎng),原文地址:http://www.xzbu.com/8/view-3801715.htm

總結(jié)

以上是生活随笔為你收集整理的Java内存不足之PermGen space错误探究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。