• JVM学习(宋红康)之运行时数据区之方法区


    栈、堆、方法区的交互关系:

    • 方法区逻辑上属于堆的一部分,但一些简单的实现可能不会触发垃圾回收和压缩。所以方法区可以看作是独立于Java堆的内存空间
    • 方法区和堆一样,是各个线程共享的内存区域
    • 方法区在虚拟机启动时就被创建,并且它的实际物理内存空间中和java堆区一样都是可以不连续的
    • 方法区的大小跟堆空间一样,可以选择固定大小或者可扩展
    • 方法区的大小决定了系统可以保存多少个类,如果系统保存了太多的类,导致方法区溢出,同样会报java.lang.OutOfMemoryError:PermGen spaceJDK7及以前)或者java.lang.OutOfMemoryError:Mataspace(JDK7以后)
    • 导致方法区会出现OOM的原因:加载大量的第三方jar包、Tomcat部署的工程过多(30-50个)、大量动态的生成反射类
    • 元空间的本质与永久代类似,都是JVM规范中方法区的实现,元空间与永久代的最大区别:元空间不在虚拟机设置的内存中,而是使用本地内存。

    设置方法区大小与OOM

    JDK7及以前;

    -XX:PermSize=100m -XX;MaxPermSize=100m

    JDK8及以后:

    -XX:MetaspaceSize=100m   -XX:MaxMetaspaceSize=100m

    简单谈如何解决OOM问题:

    方法区的内存结构:

    方法区主要用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。(域信息和方法信息可以理解为包含在类型信息之中)

    类型信息:

    域信息:

    方法信息:

    non-final的类变量:

    全局常量:static final

    被声明为final的类变量的处理方法则不同,每个全局常量在编译的时候就会被分配了

    • 对于只有static修饰的变量,在prepare阶段时,将其赋值为0,在initialization时才进行赋值
    • 而对于有static final修饰的变量,编译后就将其赋值

    • 字节码文件中的常量池当随着字节码文件被加载到方法区时,此时就变成了运行时常量池
    • 常量池中包含各种字面量和对类型、域、方法的符号引用:数值量、字符串值、类引用、字段引用、方法引用

    为什么需要常量池?

    在使用一些公共的信息的时候可以直接保存它的引用而不是它本身,让程序本身更小。

    运行时常量池是方法区的一部分,运行时常量池相较于常量池而言,具有动态性

    方法区的演进细节:

    JDK1.6及之前:有永久代,静态变量存放在永久代上

    JDK1.7:有永久代,但已经将字符串常量池和静态变量移除,保存在堆中

    JDK1.8及以后:无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆

    图解:

    利用元空间替换永久代的原因;

    • 为永久代设置空间大小是很难确定的,如果设置空间较小,则出现fullGC次数较多,出现STW影响性能,分配较大会浪费空间
    • 对永久代进行调优是比较困难的

    调整StringTable的原因:

    Jdk7中将StringTable放到了堆空间中,因为永久代回收效率很低,在fullGC的时候才会触发。而fullGC是老年代空间不足才会触发,这就导致StringTable回收效率不高,放到堆里面,能及时回收内存。

    结论:!!!

    静态引用对应的对象实体始终都在堆空间,JDK7以后的版本将静态变量(public static int num=10;其中的num)存放在堆中。

    方法区(Hotspot虚拟机中为永久代(JDK7及之前)/元空间(JDK8及以后))的垃圾回收:

    • 一般这个区域的垃圾回收效果很难让人满意,尤其是类型的卸载,条件相当苛刻,但这部分的垃圾回收有时又确实是有必要的。
    • 方法区垃圾回收的两个部分:常量池中废弃的常量、不再使用的类型

    常量的垃圾回收:

    类型的垃圾回收;

    常见面试题:

  • 相关阅读:
    吴恩达深度学习笔记——结构化机器学习项目(Structuring Machine Learning Projects)
    mac日历与iphone日历不无法同步问题
    Build Speech Apps using Java 21 Crack
    Ubuntu20.04离线安装Vmware tools
    [ChatGPT] 从 GPT-3.5 到 GPT-5 的进化之路 | ChatGPT和程序员 : 协作 or 取代
    安卓BLE蓝牙通讯
    关于电影的HTML网页设计-威海影视网站首页-电影主题HTM5网页设计作业成品
    golang使用channel通道实现非阻塞队列和超时阻塞队列
    告别微软加入 Linux 基金会,SONiC 在更大的开源生态中展翅高飞
    如何在Go中编写注释
  • 原文地址:https://blog.csdn.net/m0_55895641/article/details/127108131