永久代或者元空间溢出模拟

首先里面存了什么?

类型信息,常量,静态变量,即时编译后的代码缓存。

常量嘛,String.intern(),JDK6及之前可以,但是JDK7起就将字符串常量池,静态变量移入堆中了。

类型信息,即时代码缓存,基本一对一的东西。

在JDK7后,用户能动的也就它了。那只要能无限增加类型信息就行了呗。

问题简化为在运行期不断创建新的类型信息,不断加载。

cglib就可以在运行期动态创建类。

cglib默认开启了UserCache生成的代理类都会复用原先产生在缓存中的类,所以至始至终都只有一个代理类,所以不会产生内存溢出。手动关闭它,代码如下

笔者是JDK8配置-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m。 JDK6的配置自行查询

public class RealService {

    public void realMethod() {
        System.out.println("realMethod execute");
    }

    public static void main(String[] args) {

        //设置代理类生成目录
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/wangzhigang/temp");
        Enhancer enhancer = new Enhancer();
        enhancer.setUseCache(false);
        //设置超类,因为cglib基于父类 生成代理子类
        enhancer.setSuperclass(RealService.class);
        //设置回调,也就是我们的拦截处理
        enhancer.setCallback(new MyServiceInterceptor());

        //创建代理类
        RealService realService = (RealService) enhancer.create();
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
            realService = (RealService) enhancer.create();
        }
            
        //代用代理类的方法
        realService.realMethod();
    }
}
public class MyServiceInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("before exexute");
        Object result=methodProxy.invokeSuper(obj, objects);
        System.out.println("after exexute");
        return result;
    }
}
523
524
525
526
Exception in thread "main" org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
    at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
    at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:305)
    at com.hhdd.controller.book2.RealService.main(RealService.java:63)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
    at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
    ... 6 more
Caused by: java.lang.OutOfMemoryError: Metaspace
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    ... 11 more

 

posted @ 2021-04-21 17:43  aoeiuv  阅读(462)  评论(0编辑  收藏  举报