String.intern()
方法有可能對此區(qū)域造成大的影響(依賴于JVM實(shí)現(xiàn));java.lang.OutOfMemoryError: Java heap space...
log中明確指出heap space,可通過JVM參數(shù)設(shè)置堆大小、最大大小、發(fā)生OOM后dump堆上數(shù)據(jù);
一般通過分析dump數(shù)據(jù),確認(rèn)內(nèi)存中的對象是否必要,即確定是內(nèi)存泄漏還是內(nèi)存溢出;
如果是內(nèi)存泄漏,可進(jìn)一步查看泄漏對象到GC Roots的引用鏈,根據(jù)引用鏈,基本就能定位泄漏代碼的位置了;
如果是內(nèi)存溢出,則可通過增加JVM堆內(nèi)存、審查代碼,減少對象生命周期,減少程序運(yùn)行期間的內(nèi)存消耗;
java.lang.OutOfMemoryError: PermGen space...
永久代區(qū)域內(nèi)存大小可以配置,如果方法區(qū)以永久代實(shí)現(xiàn),則String.intern()
方法就可能導(dǎo)致該錯誤;
類的卸載條件非??量?,如果運(yùn)行時(shí)使用了大量的動態(tài)生成類,有可能導(dǎo)致該錯誤;
java.lang.OutOfMemoryError: ...
在dump文件中看不出明顯異常;
直接內(nèi)存區(qū)域可以通過JVM參數(shù)配置,默認(rèn)與堆最大值一樣;
java.lang.Class
對象未在任何地方被引用。而且這只是充分條件;static final
成員除外,它們在編譯期放入了常量池);java.lang.reflect
包得方法對類進(jìn)行反射調(diào)用的時(shí)候;java.lang.invoke.MethodHandle
實(shí)例最后的解析結(jié)果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且方法句柄對應(yīng)的類未初始化;static final
成員會被放入常量池,訪問它們不會觸發(fā)類的初始化類加載的過程
java.lang.Class
對象,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問入口類加載器
雙親委派模型(Parents Delegation Model)
BootstrapClassLoader、sum.misc.Launcher$ExtClassLoader、sun.misc.Launcher$App-ClassLoader
http://wiki.jikexueyuan.com/project/notes/images/java_class_loader_relation.jpeg" alt="java_class_loader_relation.jpeg" />
除了BootstrapClassLoader,其他所有的類加載器都應(yīng)有父類加載器,而且父子關(guān)系不是以繼承方式實(shí)現(xiàn),而是以組合方式:一個(gè)類加載器收到類加載請求后,首先調(diào)用父類加載器的加載方法,每一層次均如此,如果父類加載器無法完成加載,子加載器才嘗試自己加載。
保證Java類體系的正確性。自定義ClassLoader一般把加載邏輯放在findClass中。
protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
Class<?> clazz = findLoadedClass(className);
if (clazz == null) {
ClassNotFoundException suppressed = null;
try {
clazz = parent.loadClass(className, false);
} catch (ClassNotFoundException e) {
suppressed = e;
}
if (clazz == null) {
try {
clazz = findClass(className);
} catch (ClassNotFoundException e) {
e.addSuppressed(suppressed);
throw e;
}
}
}
return clazz;
}