Java虚拟机常量池和方法区溢出实战

提示:参考深入理解Java虚拟机

Java虚拟机常量池和方法区溢出实战


前言

运行时常量池是方法区的一部分,Java虚拟机规范中描述是堆的逻辑部分,一般垃圾回收在这个区域只是针对常量池的,这个区域1.7以前叫永久代,为了配合垃圾收集,后来发现不好用,1.7开始去永久代。1.8划分成元空间。这个区域主要存储已经被虚拟机加载的类型信息,常量,静态变量等


一、常量池实战

因为我用的环境是1.8,由于JDK7以后方法区移到了元空间,字符串常量池放到了Java堆中,所以-XX:MaxPermSize参数或者-XX:MaxMeta-spaceSize都不会出现OOM,因为字符串常量池在堆中,我配置的堆空间

-Xmx6M

代码

/**
 * @author jc
 */
public class ObjectVMTest {
    static  class OOMobject{}

    public static void main(String[] args) {
    //这里用这个list是为了避免垃圾回收,这个list现在是在GCRoot集里面,这是垃圾回收的一个引用追踪算法
        List<OOMobject> list = new ArrayList<>();

        while (true) {
            list.add(new OOMobject());
        }
    }
}


结果
在这里插入图片描述

二、方法区

参数设置

-XX:MaxMetaspaceSize=10M

代码

/**
 * @author jc
 */
public class VMMethod {

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

    static class OOMOBJECT {


    }
}

结果
在这里插入图片描述


总结

常量池还有一个经典面试题

    String s2 = "qw";

        String s1 = new String("qw");
        System.out.println(s1.equals(s2));
    }

结果为true
new一个字符串的时候,会把这个字符串字面量去常量池中查找,如果有就直接返回这个字面量的引用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值