網(wǎng)頁音樂播放器java源碼(網(wǎng)頁音樂播放器java源碼是什么)
JVM之持久代與OutOfMemory 持久代 Permanent Generation space(JDK1.7及以下版本存在)
主要存放存放class文件中類的版本、字段、方法、接口,類和方法的元數(shù)據(jù)等描述信息,運(yùn)行時常量池,用于存放編譯器生成的各種字面量和符號引用。
上限是MaxPermSize
PremGen與old區(qū)綁定在一起,在fullGC時會一起被GC
PermGen中方法區(qū)移至Metaspace,字符串常量移至Java Heap。類的元數(shù)據(jù)信息(metadata)還在,只不過不再是存儲在連續(xù)的堆空間上,而是移動到叫做“Metaspace”的本地內(nèi)存(Native memory)中。
** MetaSpace組成
**
Klass Metaspace:用來存klass的(class文件在jvm里的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)),這塊內(nèi)存是緊接著Heap的。
NoKlass Metaspace:專門來存klass相關(guān)的其他的內(nèi)容,比如method,constantPool等,這塊內(nèi)存是由多塊內(nèi)存組合起來的,所以可以認(rèn)為是不連續(xù)的內(nèi)存塊組成的。這塊內(nèi)存是必須的,雖然叫做NoKlassMetaspace,但是也其實(shí)可以存klass的內(nèi)容,上面已經(jīng)提到了對應(yīng)場景。如果KlassMetaspace用完了,那就會OOM了,不過一般情況下不會,NoKlassMestaspace是由一塊塊內(nèi)存慢慢組合起來的,在沒有達(dá)到限制條件的情況下,會不斷加長這條鏈,讓它可以持續(xù)工作。
-XX:MetaspaceSize,初始空間大小,達(dá)到該值就會觸發(fā)垃圾收集進(jìn)行類型卸載,同時GC會對該值進(jìn)行調(diào)整。
-XX:MaxMetaspaceSize,最大空間,默認(rèn)是沒有限制的(自增)。 建議設(shè)置,如果出現(xiàn)內(nèi)存增長不釋放,會占用所有的內(nèi)存空間直至被OS kill掉。
-XX:CompressedClassSpaceSize,默認(rèn)1G,這個參數(shù)主要是設(shè)置KlassMetaspace的大小,不過這個參數(shù)設(shè)置了也不一定起作用,前提是能開啟壓縮指針,假如Xmx超過了32G,壓縮指針是開啟不來的。如果有Klass Metaspace,那這塊內(nèi)存是和Heap連著的。
-XX:InitialBootClassLoaderMetaspaceSize,64位下默認(rèn)4M,32位下默認(rèn)2200K,NoKlassMetaspace是由一塊塊內(nèi)存組合起來的,這個參數(shù)決定了NoKlassMetaspace的第一個內(nèi)存Block的大小,即2*InitialBootClassLoaderMetaspaceSize,同時為bootstrapClassLoader的第一塊內(nèi)存chunk分配了InitialBootClassLoaderMetaspaceSize的大小。
-XX:MinMetaspaceExpansion和XX:MaxMetaspaceExpansion ,默認(rèn)分別是332.8K和5.2M,這兩個值為了增大觸發(fā)metaspace GC的閾值。gcLocker或者should_concurrent_collect的一些場景,因?yàn)檫@些場景下接下來會做一次GC,相信在接下來的GC中可能會釋放一些metaspace的內(nèi)存,于是先臨時擴(kuò)大下metaspace觸發(fā)GC的閾值,而有些內(nèi)存分配失敗其實(shí)正好是因?yàn)檫@個閾值觸頂導(dǎo)致的,于是可以通過增大閾值暫時繞過去。
-XX:MinMetaspaceFreeRatio和XX:MaxMetaspaceFreeRatio ,默認(rèn)分別是默認(rèn)40和70,主要是影響觸發(fā)metaspaceGC的閾值。每次GC完之后,假設(shè)我們允許接下來metaspace可以繼續(xù)被commit的內(nèi)存占到了被commit之后總共committed的內(nèi)存量的MinMetaspaceFreeRatio%,如果這個總共被committed的量比當(dāng)前觸發(fā)metaspaceGC的閾值要大,那么將嘗試做擴(kuò)容,增大觸發(fā)metaspaceGC的閾值,不過這個增量至少是MinMetaspaceExpansion才會做,不然不會增加這個閾值。這個參數(shù)主要是為了避免觸發(fā)metaspaceGC的閾值和gc之后committed的內(nèi)存的量比較接近,于是將這個閾值進(jìn)行擴(kuò)大。一般情況下在gc完之后,如果被committed的量還是比較大的時候,換個說法就是離觸發(fā)metaspaceGC的閾值比較接近的時候,這個調(diào)整會比較明顯。
先了解下內(nèi)存泄漏與內(nèi)存溢出的區(qū)別
out of memory:是指程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請了一個integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。
memory leak:是指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會被占光。
memory leak會最終會導(dǎo)致out of memory! JVM常見內(nèi)存溢出區(qū)域 堆溢出 java.lang.OutOfMemoryError:Java heap space 堆溢出GC過程:
Eden內(nèi)存不夠》進(jìn)入old分配》分配失敗觸發(fā)youngGC》分配失敗觸發(fā)fullGC(soft reference不會被強(qiáng)制回收)》分配失敗再強(qiáng)制fullGC(包括soft reference)》分配失敗拋出OOM
檢查程序,看是否有死循環(huán)或不必要地重復(fù)創(chuàng)建大量對象。
增加Java虛擬機(jī)中Xms(初始堆大?。┖蚗mx(最大堆大小)參數(shù)的大小。
打印heapdump文件和GC日志分析:-Xmx1536m -Xms1536m -Xmn1024m -XX:SurvivorRatio=4 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=路徑 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log
永久區(qū)是存放類元數(shù)據(jù)的區(qū)域。JDK1.8中,永久區(qū)被一塊元數(shù)據(jù)的區(qū)域替代。
應(yīng)用程序清理引用來觸發(fā)類卸載。
增加MaxPermSize的大小。
減少系統(tǒng)需要的類的數(shù)量。
使用classloader合理地裝載各個類,并定期回收。
太多的類或太大的類加載到元空間。
內(nèi)存泄露會耗盡整個本地內(nèi)存,導(dǎo)致內(nèi)存交換(swapping)
設(shè)置XX:MaxMetaspaceSize的大小。
java的NIO中支持直接內(nèi)存使用,可以通過java代碼獲取的一塊堆外的內(nèi)存空間,這塊內(nèi)存是直接向操作系統(tǒng)申請的,其申請速度比堆內(nèi)存慢,是訪問速度要快于堆內(nèi)存。此空間沒有被JVM完全托管,使用不當(dāng)會造成內(nèi)存溢出。
設(shè)置-XX:MaxDirectMenorySize。若不設(shè)置最大內(nèi)存可以使用到Xmx的值(建議)
使用完畢后執(zhí)行system.gc(慎用)
每個線程都要占用內(nèi)存空間,因此當(dāng)線程數(shù)量太多時,也有可能導(dǎo)致OOM,由于線程的??臻g是堆外內(nèi)存分配的,因此與直接內(nèi)存非常相似。
問題引發(fā):
線程的??臻g在堆外內(nèi)存分配,線程太多導(dǎo)致OOM
嘗試減少堆空間(Xmx)
減少每一個線程所占的內(nèi)存空間,使用Xss參數(shù)(默認(rèn)1M)可以指定線程的??臻g
減少線程數(shù)
GC overhead limt exceed檢查是Hotspot VM 1.6定義的一個策略,通過統(tǒng)計(jì)GC時間來預(yù)測是否要OOM了,提前拋出異常,防止OOM發(fā)生。Sun 官方對此的定義是:“并行/并發(fā)回收器在GC回收時間過長時會拋出OutOfMemroyError。過長的定義是,超過98%的時間用來做GC并且回收了不到2%的堆內(nèi)存。用來避免內(nèi)存過小造成應(yīng)用不能正常工作
假如生產(chǎn)環(huán)境中遇到了這個問題,在不知道原因時不要簡單地猜測和規(guī)避??梢酝ㄟ^**-verbose:gc -XX:+PrintGCDetails 看下到底什么原因造成了異常。通常原因都是因?yàn)閛ld區(qū)占用過多導(dǎo)致頻繁Full GC**,最終導(dǎo)致GC overhead limit exceed。如果gc log不夠可以借助于JProfile等工具查看內(nèi)存的占用,old區(qū)是否有內(nèi)存泄露。分析內(nèi)存泄露還有一個方法**-XX:+HeapDumpOnOutOfMemoryError**,這樣OOM時會自動做Heap Dump,可以拿MAT來排查了。還要留意 young區(qū),如果有過多短暫對象分配,可能也會拋這個異常 。
下載數(shù)據(jù)時文件大小超過某一峰值是會報(bào)這個錯誤。原因是在頁面點(diǎn)擊下載時,在數(shù)據(jù)庫查詢了很龐大的數(shù)據(jù)量,導(dǎo)致內(nèi)存使用增加,才會出現(xiàn)這個問題。
查看項(xiàng)目中是否有大量的死循環(huán)或有使用大內(nèi)存的代碼,優(yōu)化代碼。
JVM給出這樣一個參數(shù): -XX:UseGCOverheadLimit禁用這個檢查,其實(shí)這個參數(shù)解決不了內(nèi)存問題,只是把錯誤的信息延后,替換成 java.lang.OutOfMemoryError: Java heap space。
增大堆內(nèi)存 set JAVA_OPTS=server Xms512m Xmx1024m XX:MaxNewSize=1024m XX:MaxPermSize=1024m
如果有設(shè)置**-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=路徑,直接拿dump文件去分析,常用工具: MAT 與Visual VM(JDK自帶的jvisualvm.exe)。**
如果沒有設(shè)置,則執(zhí)行 jmap -dump:live,format=b,file=filename.bin PID ,拿到****dump文件再去分析。
淺堆:一個對象所消耗的內(nèi)存。
深堆:一個對象被回收后,可以真實(shí)釋放的內(nèi)存大小。
對象的實(shí)際大小定義為一個對象所能觸及的所有對象的淺堆大小之和,也就是通常意義上說的對象大小。與深堆相比,這個概念在日常中更容易被接受,但實(shí)際上這個概念和垃圾回收無關(guān)。
如圖所示:對象A的實(shí)際大小為A、C、D之和,但A的深堆大小為A、D之和。
展開全文
如果覺得本文對你有幫助,可以轉(zhuǎn)發(fā)關(guān)注支持一下
收藏
舉報(bào)
掃描二維碼推送至手機(jī)訪問。
版權(quán)聲明:本文由飛速云SEO網(wǎng)絡(luò)優(yōu)化推廣發(fā)布,如需轉(zhuǎn)載請注明出處。