Java内存模型:方法区,永久代,元空间

1.什么是方法区

方法区是java虚拟机规范去中定义的一种概念上的区域,具有什么功能比如:
方法区是可供各线程共享的运行时内存区域,存储了存储了类的元数据信息、静态变量、即时编译器编译后的代码(比如spring 使用IOC或者AOP创建bean时,或者使用cglib,反射的形式动态生成class信息等) 等,但并没有规定这个区域到底应该位于何处,在逻辑上是堆的一部分,为了与堆进行区分,通常又叫“非堆”

2.什么是永久代,和方法区的联系

永久代则是Hotspot虚拟机特有的概念,可以理解为hotspot虚拟机提供的方法区的具体实现,不同的JVM厂商,针对自己的JVM可能有不同的方法区实现方式,jdk1.8之前hotspot在内存中分出一块区域来储类的元信息、类变量以及内部字符串(interned string)等内容,称之为永久代,将它作为方法区来使用,这也是为什么有的人将方法区称之为"永久区",其实二者不是等价的

3.什么是元空间

下面是OpenJDK中的文档:

Hotspot’s representation of Java classes (referred to here asclass meta-data) is currently stored in a portion of the Java heap referred to as the permanent generation. In addition, interned Strings and class static variables are stored in the permanent generation. The permanent generation is managed by Hotspot and must have enough room for all the class meta-data, interned Strings and class statics used by the Java application.The proposed implementation will allocate class meta-data in native memory and move interned Strings and class statics to the Java heap. Hotspot will explicitly allocate and free the native memory for the class meta-data. Allocation of new class meta-data would be limited by the amount of available native memory rather than fixed by the value of -XX:MaxPermSize, whether the default or specified on the command line.

java8中,取消永久代,方法存放于元空间(Metaspace),元空间并不在虚拟机中,使用本地内存,它与永久代的区别在于:

  • 永久代的类元数据(class metadata)被转移到本机内存。
  • 永久代的符号引用(Symbols),字面量(interned strings),类的静态变量(class statics)转移到Java堆中,

为什么要取消永久代?

  • 字符串存在永久代中,容易出现性能问题和内存溢出。
  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

在jdk1.7之前,永久代(PermGen)的大小为8M,随着虚拟机的启动而启动,由于字符串存在于永久代中,故会出现内存溢出的情况,最典型的场景就是在 jsp 页面比较多的情况,容易出现永久代内存溢出,由于永久代使用的是本地内存,出现内存溢出的可能性较小,如果溢出也会考虑其回收问题,故而在jkd1.8之后就取消了永久代
参考:《深入理解java虚拟机》
https://www.zhihu.com/question/39990490
https://www.cnblogs.com/paddix/p/5309550.html

发布了37 篇原创文章 · 获赞 11 · 访问量 3906

猜你喜欢

转载自blog.csdn.net/Alphr/article/details/104447824
今日推荐