13JVM进阶-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

JVM内存模型

1、线程私有的数据区

1)、程序计数器

  我们知道线程是CPU调度的基本单位。在多线程情况下当线程数超过CPU数量或CPU内核数量时线程之间就要根据 时间片轮询抢夺CPU时间资源。也就是说在任何一个确定的时刻一个处理器都只会执行一条线程中的指令。因此为了线程切换后能够恢复到正确的执行位置每条线程都需要一个独立的程序计数器去记录其正在执行的字节码指令地址。

  因此程序计数器是线程私有的一块较小的内存空间其可以看做是当前线程所执行的字节码的行号指示器。如果线程正在执行的是一个 Java 方法计数器记录的是正在执行的字节码指令的地址如果正在执行的是 Native 方法则计数器的值为空。

  程序计数器是唯一一个没有规定任何 OutOfMemoryError 的区域。

2)、虚拟机栈

虚拟机栈描述的是Java方法执行的内存模型是线程私有的。每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息而且 每个方法从调用直至完成的过程对应一个栈帧在虚拟机栈中入栈到出栈的过程。其中局部变量表主要存放一些基本类型的变量int, short, long, byte, float, double, boolean, char和 对象句柄它们可以是方法参数也可以是方法的局部变量。

  虚拟机栈有两种异常情况StackOverflowError 和 OutOfMemoryError。我们知道一个线程拥有一个自己的栈这个栈的大小决定了方法调用的可达深度递归多少层次或嵌套调用多少层其他方法-Xss 参数可以设置虚拟机栈大小若线程请求的栈深度大于虚拟机允许的深度则抛出 StackOverFlowError 异常。此外栈的大小可以是固定的也可以是动态扩展的若虚拟机栈可以动态扩展大多数虚拟机都可以但扩展时无法申请到足够的内存(比如没有足够的内存为一个新创建的线程分配栈空间时)则抛出 OutofMemoryError 异常。

3)、本地方法栈

本地方法栈与Java虚拟机栈非常相似也是线程私有的区别是虚拟机栈为虚拟机执行 Java 方法服务而本地方法栈为虚拟机执行 Native 方法服务。与虚拟机栈一样本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

2、线程共享的数据区

1)、Java 堆

Java 堆的唯一目的就是存放对象实例几乎所有的对象实例和数组都在这里分配内存。Java堆是线程共享的类的对象从中分配空间这些对象通过new、newarray、 anewarray 和 multianewarray 等指令建立它们不需要程序代码来显式的释放。

  由于Java堆唯一目的就是用来存放对象实例因此其也是垃圾收集器管理的主要区域故也称为称为 GC堆。从内存回收的角度看由于现在的垃圾收集器基本都采用分代收集算法所以为了方便垃圾回收Java堆还可以分为 新生代 和 老年代 。新生代用于存放刚创建的对象以及年轻的对象如果对象一直没有被回收生存得足够长对象就会被移入老年代。新生代又可进一步细分为 eden、survivorSpace0 和 survivorSpace1。刚创建的对象都放入 edens0 和 s1 都至少经过一次GC并幸存。如果幸存对象经过一定时间仍存在则进入老年代。更多关于Java堆和分代收集算法的介绍请移步我的博文《Java 垃圾回收机制概述》。下图给出了Java堆的结构图

注意Java堆可以处于物理上不连续的内存空间中只要逻辑上是连续的即可。而且Java堆在实现时既可以是固定大小的也可以是可拓展的并且主流虚拟机都是按可扩展来实现的通过-Xmx(最大堆容量) 和 -Xms(最小堆容量)控制。如果在堆中没有内存完成实例分配并且堆也无法再拓展时将会抛出 OutOfMemoryError 异常。

2)、方法区

 方法区与Java堆一样也是线程共享的并且不需要连续的内存其用于存储已被虚拟机加载的 类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区通常和永久区(Perm)关联在一起但永久代与方法区不是一个概念只是有的虚拟机用永久代来实现方法区这样就可以用永久代GC来管理方法区省去专门内存管理的工作。根据Java虚拟机规范的规定当方法区无法满足内存分配的需求时将抛出 OutOfMemoryError 异常。

(1)、运行时常量池

  运行时常量池Runtime Constant Pool是方法区的一部分用于存放编译期生成的各种 字面量 和 符号引用。其中字面量比较接近Java语言层次的常量概念如文本字符串、被声明为final的常量值等而符号引用则属于编译原理方面的概念包括以下三类常量类和接口的全限定名、字段的名称和描述符 和 方法的名称和描述符。因为运行时常量池Runtime Constant Pool是方法区的一部分那么当常量池无法再申请到内存时也会抛出 OutOfMemoryError 异常

  运行时常量池相对于Class文件常量池的一个重要特征是具备动态性。Java语言并不要求常量一定只有编译期才能产生运行期间也可能将新的常量放入池中比如字符串的手动入池方法intern()。

3)、Java堆 与 方法区的区别

  Java堆是 Java代码可及的内存是留给开发人员使用的而非堆Non-Heap是JVM留给自己用的所以方法区、JVM内部处理或优化所需的内存 (如JIT编译后的代码缓存)、每个类结构 (如运行时常量池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。

说一下 JVM 有哪些垃圾回收器
Serial最早的单线程串行垃圾回收器。
Serial OldSerial 垃圾回收器的老年版本同样也是单线程的可以作为 CMS 垃圾回收器的备选预案。
ParNew是 Serial 的多线程版本。
Parallel 和 ParNew 收集器类似是多线程的但 Parallel 是吞吐量优先的收集器可以牺牲等待时间换取系统的吞吐量。
Parallel Old 是 Parallel 老生代版本Parallel 使用的是复制的内存回收算法Parallel Old 使用的是标记-整理的内存回收算法。
CMS一种以获得最短停顿时间为目标的收集器非常适用 B/S 系统。
G1一种兼顾吞吐量和停顿时间的 GC 实现是 JDK 9 以后的默认 GC 选项。


详细介绍一下 CMS 垃圾回收器

  

CMS 是英文 Concurrent Mark-Sweep 的简称是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
CMS 使用的是标记-清除的算法实现的所以在 gc 的时候回产生大量的内存碎片当剩余内存不能满足程序运行要求时系统将会出现 Concurrent Mode Failure临时 CMS 会采用 Serial Old 回收器进行垃圾清除此时的性能将会被降低。


新生代垃圾回收器和老生代垃圾回收器都有哪些有什么区别
新生代回收器Serial、ParNew、Parallel Scavenge
老年代回收器Serial Old、Parallel Old、CMS
整堆回收器G1
  新生代垃圾回收器一般采用的是复制算法复制算法的优点是效率高缺点是内存利用率低老年代回收器一般采用的是标记-整理的算法进行垃圾回收。


简述分代垃圾回收器是怎么工作的
分代回收器有两个分区老生代和新生代新生代默认的空间占比总空间的 1/3老生代的默认占比是 2/3。
新生代使用的是复制算法新生代里有 3 个分区Eden、To Survivor、From Survivor它们的默认占比是 8:1:1它的执行流程如下
把 Eden + From Survivor 存活的对象放入 To Survivor 区
清空 Eden 和 From Survivor 分区
From Survivor 和 To Survivor 分区交换From Survivor 变 To SurvivorTo Survivor 变 From Survivor。
每次在 From Survivor 到 To Survivor 移动时都存活的对象年龄就 +1当年龄到达 15默认配置是 15时升级为老生代。大对象也会直接进入老生代。
老生代当空间占用到达某个值之后就会触发全局垃圾收回一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。


说一下 JVM 调优的工具
JDK 自带了很多监控工具都位于 JDK 的 bin 目录下其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
jconsole用于对 JVM 中的内存、线程和类等进行监控
jvisualvmJDK 自带的全能分析工具可以分析内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。


常用的 JVM 调优的参数都有哪些

-Xms2g初始化推大小为 2g
-Xmx2g堆最大内存为 2g
-XX:NewRatio=4设置年轻的和老年代的内存比例为 1:4
-XX:SurvivorRatio=8设置新生代 Eden 和 Survivor 比例为 8:2
–XX:+UseParNewGC指定使用 ParNew + Serial Old 垃圾回收器组合
-XX:+UseParallelOldGC指定使用 ParNew + ParNew Old 垃圾回收器组合
-XX:+UseConcMarkSweepGC指定使用 CMS + Serial Old 垃圾回收器组合
-XX:+PrintGC开启打印 gc 信息
-XX:+PrintGCDetails打印 gc 详细信息。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6