JVM学习笔记

it2023-07-16  74

1、JVM

Java虚拟机JVM由一下部分组成: 1. 类装载子系统:该部分将Java类装载到运行时数据区内。 2. 运行时数据区:该部分主要用于存储Java运行时所需的数据信息。 2.1 堆 2.2 方法区(元空间) 2.3 栈 2.4 本地方法栈 2.5 程序计数器 3. 字节码执行引擎:该部分用于执行运行时数据区的数据。

1.1 栈

栈: 栈是线程私有的由一个个栈帧组成遵循先进后出的原则,每一个栈帧都对应一个方法,用于存储这个方法的局部变量。栈帧主要用于存储存储局部变量表(包括参数)、操作数栈、方法出口和动态链表等信息。 1. 局部变量表:用于存储局部变量。 2. 操作数栈:程序在运行的过程中用于存放操作数(局部变量值)的临时的空间。 3. 动态连接:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。Class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用,一部分会在类加载阶段或第一次使用的时候转化为直接引用(如final、static域等),称为静态解析,另一部分将在每一次的运行期间转化为直接引用,这部分称为动态连接。 4. 方法出口:就是在方法中调用另外一个方法时,前一个方法将执行位置放入后面这个方法对应栈帧的方法出口中,在后面这个方法执行完成后会通过这个方法出口通知前一个方法在进入该方法时执行的位置。

1.2 程序计数器

程序计数器: 程序计数器是最小的一块内存区域,它的作用是当前线程所执行的字节码的行号指示器(也就是标记当前线程运行的位置),换句话说就是为当前线程执行位置打标以便于当前线程阻塞后恢复运行找到阻塞前的运行位置。

1.3 堆

1、堆: 堆主要存放通过关键字new创建的对象,例如:User user = new User();,其中,new User创建的对象放在堆中,而变量User user放在栈中,user的值放在栈的局部变量中并且其值为new User创建的对象在堆中的位置(引用)。 2、堆主要分为一下几个区域: 1. 年轻代: 1.1 Eden: 1.2 Survivor0: 1.3 Survivor1: 2. 老年代: 其中,老年代占2/3的区域,年轻代1/3在年轻代中Eden占这1/3区域的8/10,Survivor0和Survivor1分别占1/10。 3、关于垃圾回收 1. 在年轻代的Eden区域快占满时,会触发minor GC这个GC是由字节码执行引擎执行的。每次执行一次GC,非垃圾对象的年龄就会增加1,当对象年龄增加到15点时候该对象会被移动至永久代(老年代)。 2. 如果老年代的内存快占满时,会触发full GC这个GC也是由字节码执行引擎执行的。当full GC也无法清理出内存时,就会出现oom(out of memory)内存溢出。注意:full GC的速度慢,因此调优的时候需要尽量的去降低full GC执行的可能性。 4、可达性分析算法: 将“GC ROOT”对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象。 5、GC ROOT根结点: GC ROOT包括线程栈的本地变量、静态变量、本地方法栈的变量等。

1.4 方法区

方法区: 在Java1.8之后成为元空间,属于物理地址。方法区主要存放的是一些常量、静态变量和类信息。例如:public static final User user = new User();其中new User()放在堆中,而变量User user放在方法区中并且其值为new User()对象在堆上的位置(引用)。

1.5 本地方法栈

本地方法栈: 用于存放本地方法的相关信息,本地方法主要使用C语言实现。

2、Java调优工具

2.1 jvisualvm

该工具为JDK自带工具,在控制台命令窗口输入jvisualvm即可打开该工具。

2.2 调优的核心思想STW

STW(stop the world): 停止JAVA除GC线程外所有用户线程的运行。之所以需要停止用户线程的运行是因为GC使用的是可达性分析算法,如果不停止用户线程那么无法准确的确定垃圾对象和非垃圾对象。

2.3 调优

目的: 调优的目的就是为了减少GC的次数,以便于提高程序运行的流畅程度提高用户体验。因为GC是会暂停用户线程,GC的频率越高系统卡顿次数越多。

2.4 新生代与老年代

新生代数据转移到老年代的情况: 1. 当新生代年龄达到15以后会将新生代中的对象移至老年代。 2. 当新生代执行GC的时候如果一批对象从Eden区移至Survivor区域时,这一批对象的大小大于Survivor的1/2的时候,这批对象会直接移动至老年代。 3. Minor GC执行后存活的对象在Survivor区放不下时,会将部分存活的对象移至老年代,部分可能还会放在Survivor区域内。

2.5 JVM相关设置参数

参数: 1. -Xms:表示 Java 初始化堆的大小,默认值为物理内存的 1/64。 2. -Xmx:表示最大 Java 堆大小,默认值为物理内存的 1/4,一般建议堆的最大值设置为可用内存的最大值的80%。 3. -Xmn:新生代的内存空间大小,Sun官方推荐配置为整个堆的 3/8,保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。 4. -Xss:表示每个 Java 线程堆栈大小,栈不是很深, 应该是128k 够用的,大的应用建议使用 256k 或 512K,一般不易设置超过 1M,要不然容易出现out ofmemory。 5. -XX:MetaspaceSize:持久代(元数据空间)大小,默认20.8M左右主要是用于控制Full GC执行的阈值。不建议设置过大因为太大会浪费内存空间,推荐使用256M,其作用与JDK1.7以前的-XX:PermSize=64m 作用类似。 6. -XX:MaxMetaspaceSize:最大元空间大小,默认基本是无穷大,但是最好是进行设置,并与-XX:MetaspaceSize保持一致。其作用与JDK1.7以前的-XX:MaxPermSize=64m类似。

以上为个人总结的一些笔记,若有雷同纯属巧合,若有错误欢迎指出,谢谢!

最新回复(0)