美文网首页
永久代和元空间的迁移变化

永久代和元空间的迁移变化

作者: 泓落飞涯 | 来源:发表于2020-06-02 01:10 被阅读0次

1.方法区介绍

方法区与JAVA堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

方法区是虚拟机规范中的一部分,描述为堆的一个逻辑部分。
永久代和元空间都是实现方式。

2.迁移变化详解

image
  • JDK 6:有去掉永久代的计划,但还未实施。
  • JDK 7:先迁移一部分,把常量池和静态变量移到JAVA堆中,保留永久代的实现。
  • JDK 8:把常量池继续留在JAVA堆中,而把其他的几个东西放入到元空间中,从此诞生元空间的说法,移除永久代的概念。

在迁移变化过程中,方法区的核心概念从来没变过,但是内部存储的实现发生了变化。

例如:

在JDK6及以前,常量池溢出时,报

java.lang.OutOfMemoryError:PerGen space

在JDK7及以后,常量池溢出时,报

java.lang.OutOfMemoryError:Java heap space

3. 其他相关知识

3.1 String.intern()

JavaDoc介绍:

Returns a canonical representation for the string object.

A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.

也就是说:

String.intern方法首先会尝试从字符串常量池中取出字面量相同的字符串对象返回,如果没有字符串常量池中没有的话,则会该字符串对象加到池中(JDK6是拷贝,JDK7是引用),然后返回池中该字符串对象的引用(而原来的字符串对象没有销毁)。

面试题:在JDK6中输出结果

public class StrTest {
  public static void main(String[] args) {
    String str1 = new StringBuilder("编程是个").append("有趣的事情").toString();
    System.out.println(str1.intern() == str1); // false

    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str1); // false
  }
}

面试题:在JDK7中输出结果

public class StrTest {
  public static void main(String[] args) {
    String str1 = new StringBuilder("编程是个").append("有趣的事情").toString();
    System.out.println(str1.intern() == str1); // true

    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str1); // false
  }
}

分析:在JDK6中运行,会得到两个false,而在JDK7中运行,会得到一个true和一个false。产生差异的原因是,在JDK6中,inter()方法会把首次遇到的字符串实例复制到永久代的字符串常量池中存储,返回的也是永久代里面这个字符串实例的引用,而由StringBuilder创建的字符串对象实例在Java堆上,所以必然不可能是同一个引用,结果讲返回false。

而JDK7的intern()方法实现就不需要再拷贝字符串的实例到永久代了,既然字符串常量池已经移到Java堆了,拿只需要再常量池里记录以下首次吹西安的实例引用即可,因此intern()返回的引用和由StringBuilder创建的那个字符串实例就是同一个。而对str2比较返回false,这是因为"java"这个字符串在执行StringBuilder.toString()之前就已经出现过了,字符串常量池中已经有它的引用,不符合intern()方法要求"首次遇到"的原则。

image

相关文章

  • 永久代和元空间的迁移变化

    1.方法区介绍 方法区与JAVA堆一样,是各个线程共享的内存区域。它用于存储已被虚拟机加载的类型信息、常量、静态变...

  • 常用基础参数元空间MetaspaceSize讲解

    -XX:MetaspaceSize 设置元空间大小元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元...

  • java8内存结构变化

    java8移除了永久代,增加了元空间。1)java7以前的版本Hotspot的方法区位于永久代,并且永久代和堆是互...

  • JVM

    1.8同1.7比,最大的差别就是:元数据区取代了永久代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。...

  • JVM永久代和元空间的区别

    绝大部分 Java 程序员应该都见过 "java.lang.OutOfMemoryError: PermGen s...

  • 元空间

    解释 元空间是jdk1.8之后出现的,之前叫永久代 元空间就是方法区,方法区是JVM的规范,元空间是HotSpot...

  • [jvm]方法区,永久代和元空间

    1.方法区 说到方法区肯定需要了解《Java虚拟机规范》中对内存管理的划分。如图所示 这是《规范》中对内存的具体划...

  • JAVA内存模型(二) 永久代和元空间

    PermGen(永久代) 与方法区的区别 方法区是JVM规范,存储了每个类的信息(包括类的名称、方法信息、字段信息...

  • JVM 1.8 永久代---元空间 的变动

    介绍JVM的内存模型的博客:https://blog.csdn.net/q5706503/article/deta...

  • 永久代、栈内存大小怎么设置

    永久代和栈内存大小一般较为固定 永久代(元数据区)也就存放类的元数据 一般512m就够了-XX:MaxMetasp...

网友评论

      本文标题:永久代和元空间的迁移变化

      本文链接:https://www.haomeiwen.com/subject/vhhyzhtx.html