JVM方法区详解有这篇就够了

news2025/1/13 8:03:22

1、方法区在哪里

《Java虚拟机规范》中明确说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。”但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。

所以,方法区是一块独立于Java堆的内存空间。

2、方法区的基本理解

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。

  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。

  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。

  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutOfMemoryError: PermGen space (jdk1.7及以前)或者java.lang.OutOfMemoryError: Metaspace (jdk1.8及以后)

  • 加载大量的第三方的jar包;Tomcat部署的工程过多(30~50个);大量动态的生成反射类

  • 关闭JVM就会释放这个区域的内存。

3、HotSpot中方法区的演进

在jdk7及以前,习惯上把方法区,称为永久代。jdk8开始,使用元空间取代了永久代。

本质上,方法区和永久代并不等价。仅是对hotspot而言的。《Java虚拟机规范》对如何实现方法区,不做统一要求。例如:BEA JRockit / IBM J9 中不存在永久代的概念。

现在来看,当年使用永久代,不是好的idea。导致Java程序更容易OOM(超过-XX:MaxPermsize上限)

咱们以图例看看JDK7\JDK8中方法区所处的位置,做到心中有图。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代最大的区别在于:元空间不在虚拟机设置的内存中,而是使用本地内存(服务器内存)。

永久代、元空间二者并不只是名字变了,内部结构也调整了

根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出OOM异常

4、设置方法区内存的大小

方法区的大小不必是固定的,JVM可以根据应用的需要动态调整。

jdk7及以前

  • 通过来设置永久代初始分配空间。默认值是20.75M-XX:PermSize

  • 通过来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M-XX:MaxPermSize

  • 当JVM加载的类信息容量超过了这个值,会报异常OutOfMemoryError:PermGen space

liuchao at liuchaodeMBP-2 in ~
# 查看进程ID
$ jps
17766
17847 RemoteMavenServer36
55006 Launcher
55007 Test
55087 Jps

liuchao at liuchaodeMBP-2 in ~
# 查看默认 PermSize 大小   21757952 / 1024 / 1024 = 20.75
$ jinfo -flag PermSize 55007
-XX:PermSize=21757952

liuchao at liuchaodeMBP-2 in ~
# 查看默认 MaxPermSize 代下  85983232 / 1024 / 1024 = 82
$ jinfo -flag MaxPermSize 55007
-XX:MaxPermSize=85983232

JDK8及以后

  • 元数据区大小可以使用参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定

  • 默认值依赖于平台。windows下,-XX:MetaspaceSize=21M -XX:MaxMetaspaceSize=-1//即没有限制。

  • 与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出,虚拟机一样会抛出异常OutOfMemoryError:Metaspace

  • -XX:MetaspaceSize:设置初始的元空间大小。对于一个64位的服务器端JVM来说,其默认的-XX:MetaspaceSize值为21MB。这就是初始的高水位线,一旦触及这个水位线,Full GC将会被触发并卸载没用的类(即这些类对应的类加载器不再存活),然后这个高水位线将会重置。新的高水位线的值取决于GC后释放了多少元空间。如果释放的空间不足,那么在不超过MaxMetaspaceSize时,适当提高该值。如果释放空间过多,则适当降低该值。

  • 如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到Full GC多次调用。为了避免频繁地GC,建议将-XX:MetaspaceSize设置为一个相对较高的值。

举例说明方法区OOM

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * @author liuchao
 * @date 2023/2/27
 */
public class OOMTest extends ClassLoader {
    public static void main(String[] args) {
        int j = 0;
        try {
            OOMTest test = new OOMTest();
            for (int i = 0; i < 10000; i++) {
                //创建Classwriter对象,用于生成类的二进制字节码
                ClassWriter classWriter = new ClassWriter(0);
                //指明版本号,public,类名,包名,父类,接口
                classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
                //返回byte[]
                byte[] code = classWriter.toByteArray();
                //类的加载
                test.defineClass("Class" + i, code, 0, code.length); //CLass对象
                j++;
            }
        } finally {
            System.out.println(j);
        }
    }
}

5、方法区、堆、栈的关系

6、方法区内部结构

6.1、方法区存储了什么

《深入理解Java虚拟机》书中对方法区(Method Area)存储内容描述如下:

它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。

6.2、方法区内部存储结构详解

6.2.1、类型信息

对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:

  • 这个类型的完整有效名称(全名=包名.类名)

  • 这个类型直接父类的完整有效名(对于interface或是java.lang.object,都没有父类)

  • 这个类型的修饰符(public,abstract,final的某个子集)

  • 这个类型直接接口的一个有序列表

6.2.2、域(Field)信息

JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。

域的相关信息包括:域名称、域类型、域修饰符(public,private,protected,static,final,volatile,transient的某个子集)

6.2.3、方法(Method)信息

JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

  • 方法名称

  • 方法的返回类型(或void)

  • 方法参数的数量和类型(按顺序)

  • 方法的修饰符(public,private,protected,static,final,synchronized,native,abstract的一个子集)

  • 方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)

  • 异常表(abstract和native方法除外)

  • 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引

6.2.4、non-final的类变量(没有加final的类变量 public static int count = 1)

  • 静态变量和类关联在一起,随着类的加载而加载,他们成为类数据在逻辑上的一部分

  • 类变量被类的所有实例共享,即使没有类实例时,你也可以访问它

以下例子如果不了解方法区,大家的第一反应是不是就报空指针了呢?

/**
 * @author liuchao
 * @date 2023/2/27
 */
public class Test3 {
    public static void main(String[] args) {
        // 没有初始化
        Order order = null;
        order.hello();
        System.out.println(order.count);
    }
}

class Order {
    public static int count = 1;

    public static void hello() {
        System.out.println("hello!");
    }
}

实际结果确实执行了

补充说明:全局常量(static final)

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

7、方法区内部结构存储演进

  • 首先明确:只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,并不要求统一

  • Hotspot中方法区的变化:

JDK1.6及之前

有永久代(permanet),静态变量存储在永久代上

JDK1.7

有永久代,但已经逐步 “去永久代”,字符串常量池,静态变量移除,保存在堆中

JDK1.8

无永久代,类型信息,字段,方法,常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录面试问题

以下问题不分先后&#xff0c;按照印象深浅排序&#xff0c;可能一次记录不完成&#xff0c;后面想起来会及时补充&#xff0c;如有不对&#xff0c;恳请各位围观大佬多多指教&#x1f64f; 印象最深的是一道很简单很简单的题目&#xff0c;我结束面试之后赶紧代码敲敲发现答错…

简易计算器-课后程序(JAVA基础案例教程-黑马程序员编著-第十一章-课后作业)

【案例11-2】 简易计算器 【案例介绍】 1.案例描述 本案例要求利用Java Swing 图形组件开发一个可以进行简单的四则运算的图形化计算器。 2.运行结果 运行结果 【案例分析】 要制作一个计算器&#xff0c;首先要知道它由哪些部分组成&#xff0c;如下图所示&#xff1a; 一…

见山,见路,见天地:OpenHarmony的开源共建攀登

自诞生之日起&#xff0c;OpenHarmony就引起着各方的关注&#xff0c;可谓是盛况空前。但一款开源操作系统的成功&#xff0c;困难不在第一步&#xff0c;而是第一步后面的一万步。那么&#xff0c;踏出开源第一步之后的OpenHarmony&#xff0c;后面的故事如何发展了呢&#xf…

(五十三)大白话基于主键的索引是如何设计的,以及如何根据主键索引查询?

上回我们说了数据页分裂的过程&#xff0c;在你不停的往表里灌入数据的时候&#xff0c;会搞出来一个一个的数据页&#xff0c;如果你的主键不是自增的&#xff0c;他可能会有一个数据行的挪动过程&#xff0c;保证你下一个数据页的主键值都大于上一个数据页的主键值。 在这个…

开启MySQL慢查询以及慢查询日志使用

目录 要开启慢查询&#xff0c;需要关注这几个参数 打开慢查询日志 把日志文件存储在文件中 模拟慢查询 如何寻找并查看慢查询日志 把日志文件存储在表中&#xff1a; 其他关注参数 log_slow_admin_statements Slow_queries 在生产环境中&#xff1a;mysqldumpslow工具分…

问题与解决办法整理一

文章目录1. Linux报错&#xff1a;terminate called after throwing an instance of ‘std::regex_error‘ what(): regex_error;[regex报错,需要将G,GCC都要升级才可以](https://blog.csdn.net/qq_56101220/article/details/127371121)2. ctemplate时遇到连接库失败的问题,将l…

redis(12)持久化操作-RDB

前言 Redis 提供了 2 个不同形式的持久化方式&#xff1a; RDB(Redis DataBase) AOF(Append Of File) RDB 在指定的时间间隔内将内存中的数据集快照写入磁盘&#xff0c; 也就是行话讲的 Snapshot 快照&#xff0c;它恢复时是将快照文件直接读到内存里。 备份是如何执行的 Re…

自动化测试框架/工具选择

单元测试&#xff08;白盒测试&#xff09; XUnit等(一般开发自己做) 接口自动化测试&#xff08;灰盒测试&#xff09; soapUI&#xff0c;优点&#xff1a;上手快 缺点&#xff1a;商业工具 postMan&#xff1a;chrome插件 优点&#xff1a;免费 缺点&#xff1a;用例管理…

深入了解Apache InLong和重点理解Sort的应用

深入了解Apache InLong和重点理解Sort的应用一、产品优势二、产品架构三、模块四、已支持数据节点五、基本概念六、Agent 插件七、Sort插件八、Manager 插件九、DataProxy插件十、重点理解Sort的应用1.支持多种数据节点2.安装部署3.启动 InLong Sort 任务4.MySQL to PostgreSQL…

数据库——3.数据库的设计规范(实用版)

前面也出过一篇文章&#xff0c;那篇文章里面详细介绍了数据库的设计规范&#xff0c;包括方方面面的内容。说实话&#xff0c;其实里面好多东西都是一种习惯的问题&#xff0c;用不用都影响不大&#xff0c;只要知道那个概念&#xff0c;遇见时能理解&#xff0c;需要时会使用…

云原生可观察性工具泛滥的思考

前言 对于采用容器环境和kubernetes的公司来说&#xff0c;可观察性正变得越来越重要。CNCF最近的一份报告发现&#xff0c;72%的受访者使用了多达9种不同的工具来监控他们的云原生环境和应用程序。当然&#xff0c;如果不使用足够的监控工具&#xff0c;可能会导致隐藏的安全…

【链表OJ题(一)】移除链表元素

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录链表OJ题(一)1. 移除…

FreeRTOS入门(06):任务通知

文章目录目的基础说明使用演示作为二进制信号量作为计数信号量作为事件组作为队列或邮箱相关函数总结目的 任务通知&#xff08;TaskNotify&#xff09;是RTOS中相对常用的用于任务间交互的功能&#xff0c;这篇文章将对相关内容做个介绍。 本文代码测试环境见前面的文章&…

「JVM 高效并发」锁优化

为了线程间更高效的共享数据及解决竞争问题&#xff0c;提高程序执行效率&#xff0c;JDK 6 做了大量锁优化&#xff0c;如适应性自旋&#xff08;Adaptive Spinning&#xff09;、锁消除&#xff08;Lock Elimination&#xff09;、锁膨胀&#xff08;Lock Coarsening&#xf…

2、监控界面设计

【任务描述】本任务要求使用相对布局或约束布局以及相应的控件完成智慧园区监控系统界面开发一、相对布局&#xff08;RelativeLayout&#xff09;概述相对布局&#xff08;RelativeLayout&#xff09;是一种根据父容器和兄弟控件作为参照来确定控件位置的布局方式。使用相对布…

《机器学习》- 习题解析 - 第一章

《机器学习》- 习题 - 第一章 文章目录《机器学习》- 习题 - 第一章一、示例-计算表1.1中的版本空间二、习题 1 - 计算题目中的版本空间三、单个合取式&析合范式的概念四、习题 2 - 计算题目中假设空间的规模大小一、示例-计算表1.1中的版本空间 首先从概念上理解版本空间…

一起玩转开源数据库!OceanBase DevCon 之开源生态全景解析

​ 2023 年 3 月 25 日&#xff0c;首次 OceanBase 开发者大会将在北京举办&#xff0c;OceanBase 首席科学家阳振坤与 OceanBase CTO 杨传辉领携众多技术专家&#xff0c;将与开发者共同探讨单机分布式、云原生、HTAP 等数据库前沿趋势&#xff0c;OceanBase 开源技术全景生…

数据库——1.数据库设计的三大范式

这篇文章我们主要来讲一下数据库设计的三大范式&#xff0c;这个还是很有用的。 目录 1.概述 2.第一范式 3.第二范式 4.第三范式 5.小结 1.概述 为了建立冗余较小、结构合理的数据库&#xff0c;设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范…

Python每日一练(20230301)

目录 1. 只出现一次的数字 2. 以特殊格式处理连续增加的数字 3. 最短回文串 1. 只出现一次的数字 给定一个非空整数数组&#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 说明&#xff1a; 你的算法应该具有线性…

「TCG 规范解读」基础设施架构和协议 (2)

可信计算组织&#xff08;Ttrusted Computing Group,TCG&#xff09;是一个非盈利的工业标准组织&#xff0c;它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立&#xff0c;并采纳了由可信计算平台联盟&#xff08;the Trusted Computing Platform Alli…