java8中使用Metaspace就不會出現OOM嗎?
阿新 • • 發佈:2019-01-08
前言:在java8中,Metaspace的出現,使我們現在不會再遇到java.lang.OutOfMemoryError: PermGen問題,但是我們要記住,這個新特性並不會使類載入導致的記憶體洩露就此消失。
(一)Metaspace的簡單介紹
(1)記憶體模型:大部分類元資料都在本地記憶體分配,用於描述類元資料的“klasses“已經被移除。
(2) 容量:預設情況下只受本地記憶體限制,但是我們可以限制。
(二)接下來看看Metaspace會不會出現OOM
我們可以通過動態代理來生成大量的代理類資訊填充元資料區。程式碼如下
public interface MetaspaceFacade {
void method(String input);
}
public class MetaspaceFacadeImpl implements MetaspaceFacade {
public void method(String name) {
}
}
public class MetaspaceFacadeInvocationHandler implements InvocationHandler {
private Object classAImpl;
public MetaspaceFacadeInvocationHandler(Object impl) {
this .classAImpl = impl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(classAImpl, args);
}
}
public class ClassMetadataLeakSimulator {
private static Map<String, MetaspaceFacade> classLeakingMap = new HashMap<String, MetaspaceFacade>();
private final static int NB_ITERATIONS_DEFAULT = 50000;
/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Class metadata leak simulator");
int nbIterations = NB_ITERATIONS_DEFAULT;
try {
for (int i = 0; i < nbIterations; i++) {
String fictiousClassloaderJAR = "file:" + i + ".jar";
URL[] fictiousClassloaderURL = new URL[] { new URL(fictiousClassloaderJAR) };
URLClassLoader newClassLoader = new URLClassLoader(fictiousClassloaderURL);
MetaspaceFacade t = (MetaspaceFacade) Proxy.newProxyInstance(newClassLoader,
new Class<?>[] { MetaspaceFacade.class },
new MetaspaceFacadeInvocationHandler(new MetaspaceFacadeImpl()));
classLeakingMap.put(fictiousClassloaderJAR, t);
}
}
catch (Throwable any) {
System.out.println("ERROR: " + any);
}
System.out.println("Done!");
}
}
1,首先不進行任何設定(需要保證堆大小),執行得到下面的截圖
可以看出,Metaspace進行了動態擴充套件,本地記憶體達到了300多M,載入超過5萬個類後還沒有出現OOM事件。接下來我們限定一下
2,虛擬機器引數配置如下:-Xmx2g -Xms2g -Xmn1g -XX:+PrintGCDetails -XX:MaxMetaspaceSize=128m,執行得到下面的截圖
可以看出,此時Metaspace被耗盡,將會丟擲OOM事件。這裡要注意MaxPermSize的區別,MaxMetaspaceSize並不會在jvm啟動的時候分配一塊這麼大的記憶體出來,而MaxPermSize是會分配一塊這麼大的記憶體的。
那麼問題來了,如果我們不設定MaxMetaspaceSize,那麼我們能用到系統的全部記憶體嗎??
metaspace很可能因為被無止境使用而被OS Kill,所以一般還是設定比較好。