Java8及以后的版本使用Metaspace来替代永久代。

    Metaspace是方法区在HotSpot中的实现,它与持久代最大的区别在于:Metaspace并不在虚拟机内存中而是使用本地内存。

    也即在java8中,class metadata,被存储在叫作Metaspace的native memory中。

    永久代(java8后被原空间Metaspace取代了)存放了以下信息:

    • 虚拟机加载的类信息
    • 常量池
    • 静态变量
    • 即时编译后的代码

    模拟Metaspace空间溢出,我们不断生成类忘原空间添加,类占据的空间总是会超过Metaspace指定的空间大小。

    1. public class MetaspaceDemo {
    2. static class OOMTest {
    3. }
    4. public static void main(String[] args) {
    5. int i = 0;
    6. try {
    7. while (true) {
    8. i++;
    9. Enhancer enhancer = new Enhancer();
    10. enhancer.setSuperclass(OOMTest.class);
    11. enhancer.setUseCache(false);
    12. enhancer.setCallback(new MethodInterceptor() {
    13. @Override
    14. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    15. return methodProxy.invokeSuper(o, args);
    16. }
    17. });
    18. enhancer.create();
    19. }
    20. } catch (Throwable e) {
    21. System.out.println("****i=" + i);
    22. e.printStackTrace();
    23. }
    24. }
    25. }
    参数配置: -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=10m

    Java虚拟机OOM之Metaspace - 图1