JVM知识

1 什么是jvm?

https://blog.csdn.net/a111042555/article/details/126284746

JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。

 

2 jdk、jre、jvm是什么关系?

(1)JRE(Java Runtime Environment),也就是java平台。所有的java程序都要在JRE环境下才能运行。
(2)JDK(Java Development Kit),是开发者用来编译、调试程序用的开发包。JDK也是JAVA程序需要在JRE上运行。
(3)JVM(Java Virtual Machine),是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。
Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。

3 JVM原理

(1)jvm是java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
(2)java编译器只要面向jvm,生成jvm能理解的字节码文件。java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码,通过特定平台运行。

执行过程:

  1. 加载.class文件
  2. 管理并分配内存
  3. 执行垃圾收集

 

4 双亲委派机制

启动类加载器:这个类加载器主要是加载存放在<JAVA_HOME>\lib目录,或者是被-Xbootclasspath参数所指定路径下,而写是java虚拟机能够识别的类库加载到虚拟机的内存中。

扩展类加载器:这个类加载器是在类sun.misc.Launcher$ExtClassLoader中以Java代码实现的,它负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的类库。

应用程序类加载器:这个类加载器是在类sun.misc.Launcher$AppClassLoader中以java代码实现的,它负责加载用户类路径上所有的类库。

双亲委派机制的工作过程是:当类加载器收到了类加载的请求时,它首先不会去自己加载这个类,而是将这个类委派给父加载器去完成,每一层的加载器都是如此。所以说每次类的加载,都会传送到顶层的启动类加载器。当父加载器反馈自己的无法加载此类时,才会由自己去完成加载。

 

 

 

 

5 JVM内存模型

 

 

 

 

1. 程序计数器(PC寄存器)

由于在JVM中,多线程是通过线程轮流切换来获得CPU执行时间的,因此,在任一具体时刻,一个CPU的内核只会执行一条线程中的指令,因此,为了能够使得每个线程都在线程切换后能够恢复在切换之前的程序执行位置,每个线程都需要有自己独立的程序计数器,并且不能互相被干扰。因此,对于程序计数器是不会发生内存溢出现象(OutOfMemory)的。

2. java栈

Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack).

 

3.本地方法栈

本地方法栈与Java栈的作用和原理非常相似。区别只不过是Java栈是为执行Java方法服务的,而本地方法栈则是为执行本地方法(Native Method)服务的。

 

4. 堆

Java中的堆是用来存储对象本身的以及数组(数组引用是存放在Java栈中的)。堆是被所有线程共享的,在JVM中只有一个堆。

Java Heap是Java虚拟机所管理的内存中最大的一块,它是所有线程共享的一块内存区域。几乎所有的对象实例和数组都在这类分配内存。Java Heap是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”。

一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行,堆内存逻辑上分为三部分:

    Young Generation Space 新生区 Young/New
    Tenure generation space 养老区 Old/Tenure
    Permanent Space 永久区 Perm
70%、80会触发垃圾回收。老年区满后内存溢出。永久代不属于堆内存的范畴,属于方法区。

 

怎么对jvm进行调优 -VM参数

参数备注
-Xms 初始堆大小。只要启动,就占用的堆大小,默认是内存的1/64
-Xmx 最大堆大小。默认是内存的1/4
-Xmn 新生区堆大小
-XX:+PrintGCDetails 输出详细的GC处理日志

 

5. 方法区

与堆一样,是被线程共享的区域。在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。

在Class文件中除了类的字段、方法、接口等描述信息外,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。

 此区属于共享区间,(生命周期长,垃圾回收少)

静态变量+常量+类信息(构造方法/接口定义)+运行时常量池 存在方法区中

 

6 JVM内存溢出的情况

 7 GC 垃圾回收

    - JVM内存模型以及分区,需要详细到每个区放什么
    - 堆里面的分区:Eden,survival from to,老年代,各自的特点。

JVM新创建的对象(除了大对象外)会被存放在新生代,默认占1/3堆内存空间,由于JVM频繁的创建对象,所以新生代会频繁触发Minor GC进行垃圾回收。新生代又分为Eden区,survivorForm区和survivorTo区
    - Minor GC与Full GC分别在什么时候发生

1)程序调用System.gc时可以触发;(2)系统自身来决定GC触发的时机。

Minor GC触发条件:当Eden区满时,触发Minor GC。

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不必然执行

(2)老年代空间不足

(3)方法区空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

Minor GC 是发生在新生代中的垃圾收集动作,所采用的是复制算法
Full GC 是发生在老年代的垃圾收集动作,所采用的是标记-清除算法
    - GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方?


JVM垃圾判定算法:(对象已死?)
    - 引用计数法(Reference-Counting) (不再使用)
    - 可达性分析算法(根搜索算法)

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

 

真正标记以为对象为可回收状态至少要标记两次。
第一次标记:不在 GC Roots 链中,标记为可回收对象。
第二次标记:判断当前对象是否实现了finalize() 方法,如果没有实现则直接判定这个对象可以回收,如果实现了就会先放入一个队列中。并由虚拟机建立一个低优先级的程序去执行它,随后就会进行第二次小规模标记,在这次被标记的对象就会真正被回收了!


GC垃圾回收主要有四大算法:(怎么找到已死对象并清除?)
    - 复制算法(Copying)
    - 标记清除(Mark-Sweep)
    - 标记压缩(Mark-Compact),又称标记整理
    - 分代收集算法(Generational-Collection)

GC参数:

Xms 起始内存

Xmx 最大内存

Xmn 新生代内存

Xss 栈大小。 就是创建线程后,分配给每一个线程的内存大小

-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4

-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5

-XX:MaxPermSize=n:设置持久代大小

收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
并发收集器设置
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。

链接:https://www.nowcoder.com/questionTerminal/d712bfe6954140958c953adcb6bf04d1

 

posted @ 2022-11-21 17:20  NingShare  阅读(19)  评论(0编辑  收藏  举报