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