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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

错误处理方法 java_JAVA常见错误处理方法 和 JVM内存结构

發(fā)布時(shí)間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 错误处理方法 java_JAVA常见错误处理方法 和 JVM内存结构 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

OutOfMemoryError在開發(fā)過(guò)程中是司空見慣的,遇到這個(gè)錯(cuò)誤,新手程序員都知道從兩個(gè)方面入手來(lái)解決:一是排查程序是否有BUG導(dǎo)致內(nèi)存泄漏;二是調(diào)整JVM啟動(dòng)參數(shù)增大內(nèi)存。OutOfMemoryError有好幾種情況,每次遇到這個(gè)錯(cuò)誤時(shí),觀察OutOfMemoryError后面的提示信息,就可以發(fā)現(xiàn)不同之處,如:

java.lang.OutOfMemoryError: Java heap space

java.lang.OutOfMemoryError: unable to create new native thread

java.lang.OutOfMemoryError: PermGen space

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

雖然都叫OutOfMemoryError,但每種錯(cuò)誤背后的成因是不一樣的,解決方法也要視情況而定,不能一概而論。只有深入了解JVM的內(nèi)存結(jié)構(gòu)并仔細(xì)分析錯(cuò)誤信息,才有可能做到對(duì)癥下藥,手到病除。

JVM規(guī)范

JVM規(guī)范對(duì)Java運(yùn)行時(shí)的內(nèi)存劃定了幾塊區(qū)域(詳見這里),有:JVM棧(Java Virtual Machine Stacks)、堆(Heap)、方法區(qū)(Method Area)、常量池(Runtime Constant Pool)、本地方法棧(Native Method Stacks),但對(duì)各塊區(qū)域的內(nèi)存布局和地址空間卻沒(méi)有明確規(guī)定,而留給各JVM廠商發(fā)揮的空間。

HotSpot JVM

Sun自家的HotSpot JVM實(shí)現(xiàn)對(duì)堆內(nèi)存結(jié)構(gòu)有相對(duì)明確的說(shuō)明。按照HotSpot JVM的實(shí)現(xiàn),堆內(nèi)存分為3個(gè)代:Young Generation、Old(Tenured) Generation、Permanent Generation。眾所周知,GC(垃圾收集)就是發(fā)生在堆內(nèi)存這三個(gè)代上面的。Young用于分配新的Java對(duì)象,其又被分為三個(gè)部分:Eden Space和兩塊Survivor Space(稱為From和To),Old用于存放在GC過(guò)程中從Young Gen中存活下來(lái)的對(duì)象,Permanent用于存放JVM加載的class等元數(shù)據(jù)。詳情參見HotSpot內(nèi)存管理白皮書。堆的布局圖示如下:

根據(jù)這些信息,我們可以推導(dǎo)出JVM規(guī)范的內(nèi)存分區(qū)和HotSpot實(shí)現(xiàn)中內(nèi)存區(qū)域的對(duì)應(yīng)關(guān)系:JVM規(guī)范的Heap對(duì)應(yīng)到Y(jié)oung和Old Generation,方法區(qū)和常量池對(duì)應(yīng)到Permanent Generation。對(duì)于Stack內(nèi)存,HotSpot實(shí)現(xiàn)也沒(méi)有詳細(xì)說(shuō)明,但HotSpot白皮書上提到,Java線程棧是用宿主操作系統(tǒng)的棧和線程模型來(lái)表示的,Java方法和native方法共享相同的棧。因此,可以認(rèn)為在HotSpot中,JVM棧和本地方法棧是一回事。

操作系統(tǒng)

由于一個(gè)JVM進(jìn)程首先是一個(gè)操作系統(tǒng)進(jìn)程,因此會(huì)遵循操作系統(tǒng)進(jìn)程地址空間的規(guī)定。32位系統(tǒng)的地址空間為4G,即最多表示4GB的虛擬內(nèi)存。在Linux系統(tǒng)中,高地址的1G空間(即0xC0000000~0xFFFFFFFF)被系統(tǒng)內(nèi)核占用,低地址的3G空間(即0×00000000~0xBFFFFFFF)為用戶程序所使用(顯然JVM進(jìn)程運(yùn)行在這3G的地址空間中)。這3G的地址空間從低到高又分為多個(gè)段;Text段用于存放程序二進(jìn)制代碼;Data段用于存放編譯時(shí)已初始化的靜態(tài)變量;BSS段用于存放未初始化的靜態(tài)變量;Heap即堆,用于動(dòng)態(tài)內(nèi)存分配的數(shù)據(jù)結(jié)構(gòu),C語(yǔ)言的malloc函數(shù)申請(qǐng)的內(nèi)存即是從此處分配的,Java的new實(shí)例化的對(duì)象也是自此分配。不同于前面三個(gè)段,Heap空間是可變的,其上界由低地址向高地址增長(zhǎng)。內(nèi)存映射區(qū),加載的動(dòng)態(tài)鏈接庫(kù)位于這個(gè)區(qū)中;Stack即棧空間,線程的執(zhí)行即是占用棧內(nèi)存,棧空間也是可變的,但它是通過(guò)下界從高地址向低地址移動(dòng)而增長(zhǎng)的。詳情參見這里。圖示如下:

JVM本身是由native code所編寫的,所以JVM進(jìn)程同樣具有Text/Data/BSS/Heap/MemoryMapping/Stack等內(nèi)存段。而Java語(yǔ)言的Heap應(yīng)當(dāng)是建立在操作系統(tǒng)進(jìn)程的Heap之上的,Java語(yǔ)言的Stack應(yīng)該也是建立操作系統(tǒng)進(jìn)程Stack之上的。 綜合HotSpot的內(nèi)存區(qū)域和操作系統(tǒng)進(jìn)程的地址空間,可以大致得到下列圖示:

Java線程的內(nèi)存是位于JVM或操作系統(tǒng)的棧(Stack)空間中,不同于對(duì)象——是位于堆(Heap)中。這是很多新手程序員容易誤解的地方。注意,“Java線程的內(nèi)存”這個(gè)用詞不是指Java.lang.Thread對(duì)象的內(nèi)存,java.lang.Thread對(duì)象本身是在Heap中分配的,當(dāng)調(diào)用start()方法之后,JVM會(huì)創(chuàng)建一個(gè)執(zhí)行單元,最終會(huì)創(chuàng)建一個(gè)操作系統(tǒng)的native thread來(lái)執(zhí)行,而這個(gè)執(zhí)行單元或native thread是使用Stack內(nèi)存空間的。

經(jīng)過(guò)上述鋪墊,可以得知,JVM進(jìn)程的內(nèi)存大致分為Heap空間和Stack空間兩部分。Heap又分為Young、Old、Permanent三個(gè)代。Stack分為Java方法棧和native方法棧(不做區(qū)分),在Stack內(nèi)存區(qū)中,可以創(chuàng)建多個(gè)線程棧,每個(gè)線程棧占據(jù)Stack區(qū)中一小部分內(nèi)存,線程棧是一個(gè)LIFO數(shù)據(jù)結(jié)構(gòu),每調(diào)用一個(gè)方法,會(huì)在棧頂創(chuàng)建一個(gè)Frame,方法返回時(shí),相應(yīng)的Frame會(huì)從棧頂移除(通過(guò)移動(dòng)棧頂指針)。在這每一部分內(nèi)存中,都有可能會(huì)出現(xiàn)溢出錯(cuò)誤。回到開頭的OutOfMemoryError,下面逐個(gè)說(shuō)明錯(cuò)誤原因和解決方法(每個(gè)OutOfMemoryError都有可能是程序BUG導(dǎo)致,因此解決方法不包括對(duì)BUG的排查)。

java.lang.OutOfMemoryError: Java heap space

原因:Heap內(nèi)存溢出,意味著Young和Old generation的內(nèi)存不夠。

解決:調(diào)整java啟動(dòng)參數(shù) -Xms -Xmx 來(lái)增加Heap內(nèi)存。

java.lang.OutOfMemoryError: unable to create new native thread

原因:Stack空間不足以創(chuàng)建額外的線程,要么是創(chuàng)建的線程過(guò)多,要么是Stack空間確實(shí)小了。

解決:由于JVM沒(méi)有提供參數(shù)設(shè)置總的stack空間大小,但可以設(shè)置單個(gè)線程棧的大小;而系統(tǒng)的用戶空間一共是3G,除了Text/Data/BSS/MemoryMapping幾個(gè)段之外,Heap和Stack空間的總量有限,是此消彼長(zhǎng)的。因此遇到這個(gè)錯(cuò)誤,可以通過(guò)兩個(gè)途徑解決:1.通過(guò)-Xss啟動(dòng)參數(shù)減少單個(gè)線程棧大小,這樣便能開更多線程(當(dāng)然不能太小,太小會(huì)出現(xiàn)StackOverflowError);2.通過(guò)-Xms -Xmx 兩參數(shù)減少Heap大小,將內(nèi)存讓給Stack(前提是保證Heap空間夠用)。

java.lang.OutOfMemoryError: PermGen space

原因:Permanent Generation空間不足,不能加載額外的類。

解決:調(diào)整-XX:PermSize= -XX:MaxPermSize= 兩個(gè)參數(shù)來(lái)增大PermGen內(nèi)存。一般情況下,這兩個(gè)參數(shù)不要手動(dòng)設(shè)置,只要設(shè)置-Xmx足夠大即可,JVM會(huì)自行選擇合適的PermGen大小。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

原因:這個(gè)錯(cuò)誤比較少見(試著new一個(gè)長(zhǎng)度1億的數(shù)組看看),同樣是由于Heap空間不足。如果需要new一個(gè)如此之大的數(shù)組,程序邏輯多半是不合理的。

解決:修改程序邏輯吧。或者也可以通過(guò)-Xmx來(lái)增大堆內(nèi)存。

在GC花費(fèi)了大量時(shí)間,卻僅回收了少量?jī)?nèi)存時(shí),也會(huì)報(bào)出OutOfMemoryError,我只遇到過(guò)一兩次。當(dāng)使用-XX:+UseParallelGC或-XX:+UseConcMarkSweepGC收集器時(shí),在上述情況下會(huì)報(bào)錯(cuò),在HotSpot GC Turning文檔上有說(shuō)明:

The parallel(concurrent) collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown.

對(duì)這個(gè)問(wèn)題,一是需要進(jìn)行GC turning,二是需要優(yōu)化程序邏輯。

java.lang.StackOverflowError

原因:這也內(nèi)存溢出錯(cuò)誤的一種,即線程棧的溢出,要么是方法調(diào)用層次過(guò)多(比如存在無(wú)限遞歸調(diào)用),要么是線程棧太小。

解決:優(yōu)化程序設(shè)計(jì),減少方法調(diào)用層次;調(diào)整-Xss參數(shù)增加線程棧大小。

本文轉(zhuǎn)自

http://blog.csdn.net/xiaoyufu007/article/details/6429657

總結(jié)

以上是生活随笔為你收集整理的错误处理方法 java_JAVA常见错误处理方法 和 JVM内存结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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