JVM的整体结构
# 前言
Java是跨平台语言,看官方给的一张图,我们写的Java代码在最上层 ,最终通过Java虚拟机帮助我们去运行,根据不同操作系统翻译成不同的机器码运行,从而实现了跨平台的特性。
# 运行时数据区
启动java的参数示例
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar microservice-eureka-server.jar
1
-Xms:初始堆大小 -Xmx:最大堆大小 -Xmn:新生代大小 -Xss:栈大小 -XX:MetaspaceSize:初始元空间大小 -XX:MaxMetaspaceSize:最大元空间大小
# 堆
堆分为新生代和老年代,新生代又分为Eden区和Survivor区,老年代是存放长期存活的对象,新生代是存放新创建的对象。
# 方法区
方法区是一个抽象概念,在不同的Java版本中有不同的实现。 在JDK1.8之前,使用永久代实现,在JDK1.8之后,方法区被元空间取代。
方法区都存什么内容?
- 类信息
- 静态变量
- class常量池 Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译期生成的各种字面量(Literal)和符号引用(Symbolic References)。
我们一般可以通过javap命令生成更可读的JVM字节码指令文件:javap -v Math.class
# 虚拟机栈
虚拟机栈里面放的是一个个栈帧,每个栈帧对应一个方法,结构如下:
- 局部变量表 存放方法执行过程中的局部变量
- 操作数栈 存放方法执行过程中的临时变量,以及方法执行过程中的计算结果
- 动态链接 指向运行时常量池中该方法的引用
- 方法出口 方法执行完成后的返回地址
# 程序计数器
下一条指令的地址,每个线程都有一个程序计数器,不会出现内存溢出的情况。
# 本地方法栈
本地方法栈是为了执行本地方法服务的,与虚拟机栈类似,只不过是为本地方法服务的。
# 字符串常量池详解
# 字符串常量池的设计思想
字符串作为最基础的类型,会被大量的使用,如果频繁的创建字符串对象,会导致内存的浪费,所以Java设计了字符串常量池,用来存放字符串对象。
字符串常量池是在堆内存中的,不是在方法区中的。 创建字符串对象的时候,会先去字符串常量池中查找是否有相同的字符串,如果有,就返回引用,如果没有,就创建一个新的字符串对象。
字符串常量池位置
- JDK1.6 有永久代,运行时常量在永久代中,运行时常量包括字符串常量池
- JDK1.7 有永久代,运行时常量在永久代中,字符串常量池从永久代中移动到堆中
- JDK1.8+ 无永久代,运行时常量在元空间中,字符串常量池在堆中
上次更新: 2024/04/22, 10:37:52