如何使方法区溢出

方法区溢出

Java内存区域Java虚拟机栈章节介绍过,方法区主要存储类型相关信息,在JDK 6及以前版本字符串常量池也在此区域存储,JDK 7时将字符串常量池移入堆内存。
我们可以使字符串常量池类型相关信息导致内存溢出。

字符串常量池

在JDK 6及以前版本字符串常量池存储在方法区,JDK 7时将字符串常量池移入堆内存。 所以此方法只能在jdk6生效。

public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        int strCount = 0;
        while (true) {
            list.add(String.valueOf(strCount++).intern());
        }
        

}

类型相关信息

可以通过产生大量类来填满方法区,使其内存溢出。产生大量类有有多种方式,例如JDK提供的动态代理,第三方的CGLib。

public static void main(String[] args) {
        while(true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(obj,objects);
                }
            });
            enhancer.create();
        }
    }
    static class OOMObject{
        
    }

这段代码是一个典型的Java内存溢出(Out Of Memory)示例,它使用CGLib库创建无限个代理对象,从而导致内存不断增长,最终耗尽系统资源。

具体的代码逻辑如下:

  1. main方法中,使用一个无限循环while(true)来不断执行以下步骤。

  2. 创建Enhancer对象,Enhancer是CGLib库中的一个类,用于生成代理对象。

  3. 设置被代理类的父类为OOMObject类:enhancer.setSuperclass(OOMObject.class)

  4. 关闭代理对象的缓存功能,确保每次都会生成新的代理对象:enhancer.setUseCache(false)

  5. 设置回调函数,即拦截器。在这个示例中,使用了MethodInterceptor接口,并实现了其中的intercept方法。该方法会在代理对象的方法被调用时触发,通过调用methodProxy.invokeSuper方法实现对原始方法的调用。

  6. 调用enhancer.create()方法创建代理对象,并丢弃返回值。

以上步骤将会重复执行,不断创建代理对象。由于没有终止条件,内存中会不断创建新的代理对象,逐渐耗尽系统资源,最终导致内存溢出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值