zoukankan      html  css  js  c++  java
  • 深入理解jvm jdk1,7(13)

    方法区和运行时常量池溢出:
    前面提到JDK1.7还是逐步“去永久代”的事情,在此就以测试代码观察一下这件事对程序的实际影响。
    String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String对象的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。在JDK1.6及之前的版本中由于常量池分配在永久代内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量。

    public class RuntimeConstantPoolOOM {
    /**
    * -XX:PermSize=10M -XX:MaxPermSize=10M
    * @param args
    */
    public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    int i = 0;
    while (true){
    list.add(String.valueOf(i++).intern());
    }
    }
    }

    -XX:PermSize=10M      方法区初始化大小
    -XX:MaxPermSize=10M   方法区最大上限

    运行结果:
    JDK1.7 一切正常,并不会抛异常。 程序一直产生字符串常量,方法区大小为10M,程序正常 说明常量池不在方法区
    JDK1.6:
    Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
     at java.lang.String.intern(Native Method)
     at test.main(test.java:13)

    java.lang.OutOfMemoryError之后跟着 PermGen space,说明运行时常量池属于方法区(HotSpot虚拟机中的永久代)
    
    
    public class RuntimeConstantPoolOOM {
    /**
    * -XX:PermSize=10M -XX:MaxPermSize=10M
    * @param args
    */
    public static void main(String[] args) {

    String s = new StringBuilder("计算机").append("软件").toString();
    System.out.println(s.intern() == s);

    String s1 = new StringBuilder("ja").append("va").toString();
    System.out.println(s1.intern() == s1);
    }
    }
    运行结果:
    JDK1.6: false false
    JDK1.7: true  false


    JDK1.6中,intern()方法会把首次遇到的字符串实例复制到永久代中,返回的也是永久代中这个字符串实例的引用,而由StringBuilder创建的字符串实例在Java堆上,所以必然不是同一个引用,返回false。

    JDK1.7中,intern()实现不会再复制实例,只是在常量池中记录首次出现的实例引用,因此intern()返回的引用和由StringBuilder创建的那个字符串实例是同一个。s.intern() == s 返回true。

    s1返回false是因为“java”这个字符串在执行StringBuilder.toString()之前已经出现过,字符串常量池中已经有它的引用了,不符合“首次出现”的原则,而“计算机软件”这个字符串则是首次出现的,s1.inertn() == s1 返回false

    "java" 字符串在StringBuilder.toString 之前出现的位置:https://blog.csdn.net/u014333083/article/details/80354900

    
    
    public class JavaMethodAreaOOM {

    /**
    * -XX:PermSize=10M -XX:MaxPermSize=10M
    * @param args
    */
    public static void main(final 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(objects,args);
    }
    });

    enhancer.create();
    }
    }

    static class OOMObject {

    }
    }



    
    
  • 相关阅读:
    Github
    Vocabulary in Computer
    js中三种定义变量的方式const, var, let的区别
    Node.js-1
    JSON_in_js
    JSON快速入门
    Mysql tinyint长度为1时在java中被转化成boolean型
    maven上解决循环依赖、又不想新加第三模块的方法
    关于springboot和tomcat的服务能力做下简单的测试
    tomcat各个端口的作用
  • 原文地址:https://www.cnblogs.com/myDreamWillCometrue/p/10875589.html
Copyright © 2011-2022 走看看