zoukankan      html  css  js  c++  java
  • 方法区之2:jdk1.6,jdk1.7,jdk1.8下的方法区变迁

    JDK1.7及以前,HotSpot虚拟机将java类信息、常量池、静态变量、即时编译器编译后的代码等数据,存储在Perm(永久带)里(对于其他虚拟机如BEA JRockit、IBM J9等是不存在永久带概念的),类的元数据和静态变量在类加载的时候被分配到Perm里,当常量池回收或者类被卸载的时候,垃圾收集器会回收这一部分内存,但效果不太理想。

    JDK1.8时,HotSpot虚拟机对JVM模型进行了改造,将类元数据放到了本地内存中,将常量池静态变量放到了Java里,HotSpot VM将会为类的元数据明确的分配与释放本地内存
    在这种架构下,类元数据就突破了-XX:MaxPermSize的限制,所以此配置已经失效,现在可以使用更多的本地内存。这样一定程度上解决了原来在运行时生成大量的类,从而经常Full GC的问题——如运行时使用反射、代理等。

    jdk7版本以前的实现

    jdk7版本的改动是把字符串常量池移到了堆中。

    jdk8 MetaSpace

    jdk1.8中则把永久代给完全删除了,取而代之的是MetaSpace
    运行时常量池和静态变量都存储到了堆中,MetaSpace存储类的元数据,MetaSpace直接申请在本地内存中(Native memory),这样类的元数据分配只受本地内存大小的限制,OOM问题就不存在了。除此之外,还有其他很多好处:
    • Take advantage of Java Language Specification property : Classes and associated metadata lifetimes match class loader’s
    • Linear allocation only
    • No individual reclamation (except for RedefineClasses and class loading failure)
    • No GC scan or compaction
    • No relocation for metaspace objects
     jdk1.8中,常量池和静态变量都存储到了堆中,可以通过《JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap》中示例说明。
    其它元数据信息存放在元空间内,可通过《JVM异常之:方法区溢出OutOfMemoryError: PermGen space》的示例说明。

    为什么jdk1.8要把方法区从JVM里(永久代)移到直接内存(元空间)

    原因一:因为直接内存,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,也就是堆内存中的数据,如果要作IO操作,会先复制到直接内存,再利用本地IO处理。
        从数据流的角度,非直接内存是下面这样的作用链:本地IO --> 直接内存 --> 非直接内存 --> 直接内存 --> 本地IO
        而直接内存是:本地IO --> 直接内存 --> 本地IO
    原因二:整个永久代有一个 JVM 本身设置固定大小上线,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,并且永远不会得到java.lang.OutOfMemoryError。
        可以使用 -XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制
        -XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

  • 相关阅读:
    不同的ospf进程发布互联网段可以互通
    大数分解
    主席树(非权值)
    块状数组
    Codeforces Round #744 (Div. 3) G. Minimal Coverage
    记录一种从天而降的掌法(动态维护中位数的方法)
    快速统计二进制中1的数量
    网络流(小常数)
    矩阵快速幂
    米勒罗宾素性检验
  • 原文地址:https://www.cnblogs.com/duanxz/p/3726574.html
Copyright © 2011-2022 走看看