PermGen Space是Oracle-Sun Hotspot纔有的,同類產品Oralce JRockit, IBM J9, Taobao JVM 是沒有的,在Java8中永久區(PermGen)已經變成元空間(Metaspace),這裏懷舊一下。html
設置VM啓動參數 -XX:PermSize=5m -XX:MaxPermSize=5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\dump
運行下面代碼(這裏用的Maven倉庫下的jar包,根據本身狀況來),經過不斷的動態加載類(Spring常常幹這樣的事情),形成PermGen OOM. 通常JVM默認PermGen大約是80M左右(和環境也有點關係,不過八九不離十),能夠經過jmap -heap pid
查看,爲何那麼小能夠看下這個回答java
import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; public class PermGen { private static List<Object> insList = new ArrayList<Object>(); public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, MalformedURLException, InterruptedException { permLeak(); } private static void permLeak() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, MalformedURLException, InterruptedException{ for (int i = 0; i < 1000 ; i++) { URL[] urls = getURLS(); URLClassLoader loader = new URLClassLoader(urls,null); Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory",true,loader); Method getLog = logfClass.getMethod("getLog", String.class); Object result = getLog.invoke(logfClass, "TestPermGen"); insList.add(result); System.out.println(i + " : " + result); Thread.sleep(100); } } private static URL[] getURLS() throws MalformedURLException{ File libDir = new File("D:\\HHSZXA\\.m2\\repository\\commons-logging\\commons-logging\\1.1.1"); File[] subFiles = libDir.listFiles(); int count = subFiles.length; URL[] urls = new URL[count]; for (int i = 0; i < count ; i++) { urls[i] = subFiles[i].toURI().toURL(); } return urls; } }
輸出:apache
0 : org.apache.commons.logging.impl.Jdk14Logger@2babbba1 1 : org.apache.commons.logging.impl.Jdk14Logger@5d08e435 2 : org.apache.commons.logging.impl.Jdk14Logger@30d46b95 3 : org.apache.commons.logging.impl.Jdk14Logger@4ec4f498 4 : org.apache.commons.logging.impl.Jdk14Logger@7dbc345a 5 : org.apache.commons.logging.impl.Jdk14Logger@7ee361ad 6 : org.apache.commons.logging.impl.Jdk14Logger@7d94a8eb java.lang.OutOfMemoryError: PermGen space Dumping heap to d:\dump\java_pid3276.hprof ... Heap dump file created [2648239 bytes in 0.016 secs] Exception in thread "Reference Handler" Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at PermGen.permLeak(PermGen.java:25) at PermGen.main(PermGen.java:16) Caused by: java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:792) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1131) at org.apache.commons.logging.LogFactory$2.run(LogFactory.java:1065) at java.security.AccessController.doPrivileged(Native Method) at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:1062) at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:650) at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:704) ... 6 more java.lang.OutOfMemoryError: PermGen space at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:140)
經過控制檯信息,能夠初步斷定是方法區OOM,緣由是經過URLClassLoader類加載器加載某個動態類,這個動態類是由調用org.apache.commons.logging.LogFactory.getLog方法生成的,同時能夠看到引發的錯誤的代碼行數PermGen.java:25微信
首先看摘要
性能
其中1131行代碼,就是實例化某個類,這個類是什麼,咱們能夠改變日誌輸出級別,或者直接打印。url
一切真相大白,有興趣更深刻的童鞋,歡迎討論。spa
-XX:+CMSClassUnloadingEnabled
.net
感謝您的耐心閱讀,若是您發現文章中有一些沒表述清楚的,或者是不對的地方,請給我留言,你的鼓勵是做者寫做最大的動力,
若是您認爲本文質量不錯,讀後以爲收穫很大,不妨小額贊助我一下,讓我更有動力繼續寫出高質量的文章。日誌
做 者 : @mousycodercode
原文出處 : http://mousycoder.com/2016/01...
創做時間:2016-1-15
更新時間:2016-1-15