文章目录
- JVM的内存结构
- 程序计数器
- 虚拟机栈(栈)
- 本地方法栈
- Native关键字
- 堆
- 元空间(JDK1.8之前为永久代)
- 实例对象实例化的过程
JVM的内存结构
先看下图
内存结构分为以下的两种:线程私有以及线程共享
线程私有:程序计数器(PC寄存器),虚拟机栈,本地方法栈随着线程的产生而产生,随着线程的消失而消失。
线程共享:有堆,方法区(又叫元空间)
程序计数器
程序计数器是程序的一个标识,每条线程都需要有一个独立的程序计数器,用于存储即将执行的指令代码。
作用:
在线程数大于 CPU 数的情况下,会存在线程切换,程序计数器会记下线程即将执行的操作,这样执行线程切换的话就知道下一步要执行什么,比如顺序执行,选择,循坏,异常处理。
程序计数器的生命周期随着线程的创建而创建,随着线程的结束而死亡。
虚拟机栈(栈)
栈由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法返回地址。
- Java 虚拟机栈(简称栈)和数据结构的栈是类似的,先进后出的数据结构,只支持出栈和入栈。
- 线程私有的,它的生命周期和线程相同,随着线程的创建而创建,随着线程的死亡而死亡。
- 所有的 Java 方法(本地方法除外)调用都会通过栈来实现的。
- 每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。
-
局部变量表
局部变量表 主要存放了编译期的各种数据类型(比如:int),对象引用(reference)
-
操作数栈
操作数栈主要作为方法调用的中转站使用,用于存放方法执行过程中产生的**中间计算结果,**比如中间计算产生的临时变量。
-
动态链接
Class 文件在常量池中会保存有大量的符号引用比如方法引用的符号引用。当一个方法要调用其他方法,将其中的符号引用转换为调用方法的直接引用,这个过程也被称为动态链接。
本地方法栈
和虚拟机栈所发挥的作用类似,区别是: 而本地方法栈则为虚拟机使用到的 Native 方法服务。一般使用C语言写的方法。
Native关键字
- 不是调用Java程序,去底层调用c,c++程序
- 会进入本地方法栈,调用本地接口
- Java 本地接口(JNI)的作用就是扩展Java的使用,融合不同的语言被Java调用
- 起初Java诞生的时候,C,C++横行,所以想要立足就必须要有调用C,C++的程序
这个关键字主要是调用调用底层,硬件等,如Java程序驱动打印机,管理系统
堆
- 存储着类的信息实例对象等等,是最大的内存空间。
- 是垃圾回收机制 GC 的重要区域。
- 用于常用于调优的地方。
主要分为
- 新生区** ** 1/3
- Eden 区(伊甸园)8/10
- survive from (幸存from区)1/10
- survive to (辛存to区)1/10
- 养老区 2/3
- 元空间(JDK8之前叫永久区)
- 每次GC 都会将Eden中活对象移到幸存区中,Eden 区被 GC(垃圾回收机制) 后,就会是空的
- 幸存区 from 和 to 是动态交换的。
- 进行轻 GC 后幸存的能进入幸存区,进行重 GC 能幸存的进入养老区。
- 当一个对象经历了 15 次的GC都还没有死,就会进入养老区 可以通过-XX:MAXTenuringThreashold=5的参数来调试
- 元空间(永久代)逻辑上是存在的,物理上是不存在的。
使用idea来配置JVM传参
-Xms1024m -Xmx1024 -XX:+PrintGCDetails
- Xms:最初始化内存分配 ;一般是 本机内存的 1/64
- Xmx:最大的分配内存 ; 一般是 本机内存的1/4
- XX…:打印GC的细节
如果一个项目中出现 oom 错误应该如果排故障
- 使用命令-Xmx 进行内存扩大,看看是否还是错误,尝试扩大内存看结果
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
元空间(JDK1.8之前为永久代)
元空间是虚拟机的规范,许多厂家是没有元空间的。
元空间又名方法区,主要存储静态变量,动态变量,常量,类信息(class模板,构造方法,接口定义),运行时常量池(字符串常量池)。
实例对象实例化的过程
new test()的发生过程: 在栈中生成一个对象引用,指向堆中的实例变量,堆会根据方法区中的类信息进行加载赋值,类中字符串,会先从常量池中找初值。
如下图:
我是小辉,24 届毕业生。当下是找工作ing,欢迎关注,持续分享。