Metaspace && Heap space的內存溢出java
note that when the heap space runs out you getbash
java.lang.OutOfMemoryError: Java heap space
However when you run out of PermGen you getide
java.lang.OutOfMemoryError: PermGen space
However in jdk8 when you run out of Metaspace you getthis
java.lang.OutOfMemoryError: Metaspace
以下面代碼,模擬Metaspace的內存溢出,spa
public interface ClassA { void method(String input); } ====================== public class ClassAImpl implements ClassA { public void method(String name) { // do nothing } } ====================== public class ClassAInvocationHandler implements InvocationHandler { private Object classAImpl; public ClassAInvocationHandler(Object impl) { this.classAImpl = impl; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (Object.class == method.getDeclaringClass()) { String name = method.getName(); if ("equals".equals(name)) { return proxy == args[0]; } else if ("hashCode".equals(name)) { return System.identityHashCode(proxy); } else if ("toString".equals(name)) { return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy)) + ", with InvocationHandler " + this; } else { throw new IllegalStateException(String.valueOf(method)); } } return method.invoke(classAImpl, args); } } ====================== public class ClassMetadataLeakSimulator { private static Map<String, ClassA> classLeakingMap = new HashMap<String, ClassA>(); private final static int NB_ITERATIONS_DEFAULT = 50000; /** * @param args */ public static void main(String[] args) { System.out.println("Class metadata leak simulator"); System.out.println("Author: Pierre-Hugues Charbonneau"); System.out.println("http://javaeesupportpatterns.blogspot.com"); int nbIterations = (args != null && args.length == 1) ? Integer.parseInt(args[0]) : NB_ITERATIONS_DEFAULT; try { for (int i = 0; i < nbIterations; i++) { String fictiousClassloaderJAR = "file:" + i + ".jar"; URL[] fictiousClassloaderURL = new URL[] { new URL(fictiousClassloaderJAR) }; // Create a new classloader instance URLClassLoader newClassLoader = new URLClassLoader(fictiousClassloaderURL); // Create a new Proxy instance ClassA t = (ClassA) Proxy.newProxyInstance(newClassLoader, new Class<?>[] { ClassA.class }, new ClassAInvocationHandler(new ClassAImpl())); // Add the new Proxy instance to the leaking HashMap classLeakingMap.put(fictiousClassloaderJAR, t); } } catch (Throwable any) { System.out.println("ERROR: " + any); } System.out.println("Done!"); } }
運行上面的程序,並設置JVM參數,以下,code
➜ sample java -Xmx128m -Xms128m -XX:+UseG1GC -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=64m ClassMetadataLeakSimulator Class metadata leak simulator Author: Pierre-Hugues Charbonneau http://javaeesupportpatterns.blogspot.com ERROR: java.lang.OutOfMemoryError: Metaspace Done!
以下面這段代碼,blog
import java.util.ArrayList; import java.util.List; public class GCTest { public static void main(String args[]) { List<GCTest> list = new ArrayList<>(); for (int i = 0; i < Integer.MAX_VALUE; i++) { list.add(new GCTest()); } } }
運行程序並設置JVM參數,內存
➜ workspace java -Xmx128m -Xms128m -XX:+UseG1GC -XX:MetaspaceSize=3m -XX:MaxMetaspaceSize=3m GCTest Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3210) at java.util.Arrays.copyOf(Arrays.java:3181) at java.util.ArrayList.grow(ArrayList.java:261) at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235) at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227) at java.util.ArrayList.add(ArrayList.java:458) at GCTest.main(GCTest.java:10)
===========END===========ssl