十个问题弄清JVM&GC(一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 每个java开发同学不管是日常工作中还是面试里,都会遇到JDK、JVM和GC的问题。本文会从以下10个问题为切入点,带着大家一起全面了解一下JVM的方方面面。

十个问题弄清JVM&GC(一)

每个java开发同学不管是日常工作中还是面试里,都会遇到JDK、JVM和GC的问题。本文会从以下10个问题为切入点,带着大家一起全面了解一下JVM的方方面面。

  1. JVM、JRE和JDK的区别和联系
  2. JVM是什么?以及它的主要作用
  3. JVM的核心功能有哪些
  4. 类加载机制和过程
  5. 运行时数据区的逻辑结构
  6. JVM的内存模型
  7. 如何确定对象是垃圾
  8. 垃圾收集的算法有哪些
  9. 各种问世的垃圾收集器
  10. JVM调优的参数配置

1、JVM、JRE和JDK的区别和联系

这个基本是步入java世界的入门级知识认知,首先我们来看一下来自java官网的一张图:


从这张图里我们基本就可以看出“JRE”是运行Java语言编写的程序所不可缺少的运行环境。有了JRE我们写的java程序才可以运行起来被用户所使用。

而“JDK”俗称java开发工具包,它包括了Java运行环境JRE(Java Runtime Envirnment)以及一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。

但不管是JRE还是JDK都是以JVM为基石的。可以说JVM是java程序可以在某台机器上得以运行的最底层的保障。

2、那么什么是JVM?它的主要作用又是什么?

JVM是Java Virtual Machine(Java虚拟机)的缩写,它的用途简单的说就是它能让我们写的java程序在不同的操作系统的不同CPU上运行。我们写的java程序会利用开发工具(如Intellij idea)把它编译成.class文件,但这个class文件是不能直接被操作系统识别运行的,需要利用jvm按jvm规范将编译好的.class文件转变成机器语言,再交由操作系统提交给cpu去执行。

用一句话评价JVM的主要作用就是:JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

3、这么牛的JVM的核心功能有哪些?

JVM中核心的功能总体有三块:

  1. 类加载器:在JVM启动时或者在类运行时将需要的class文件加载到JVM中
  2. 执行引擎:负责执行class文件,包括分配运行时数据区(如程序计数器、本地方法栈和虚拟栈)和 最终将class中的字节码指令转为机器指令通过操作系统交给CPU执行
  3. 垃圾回收器:对JVM的堆内存进行管理,及时回收调无用的资源释放内存空间

4、JVM类的加载机制和过程?

首先,我们谈谈开发工具编译生成的class文件是如何被JVM加载的。所谓的类加载机制其实就是:虚拟机(JVM)把class文件加载到内存中,然后对它进行正确性的校验,检查通过再进行解析和初始化,最终把class文件变成一个内存中可以直接使用的java.lang.Class对象。

从一个class文件的装载到销毁,它的生命周期基本可以分为以下五个阶段:装载、链接(验证、准备和解析)、初始化、使用和卸载。

  1. 装载:装载(Load)阶段总共有三项工作

    (1)通过类的全限定名获取其定义的二进制字节流,需要借助类装载器(ClassLoader)完成;
    
    (2)在运行时数据区的“方法区”中分配一块区域保存这个类的信息,包括类的基本信息、常量和静态变量等等;
    
    (3)在“Java堆”内存上生成一个该类的java.lang.Class对象,用于对外暴露使用该类的入口。
    
  2. 链接:链接(link)阶段同样有三项工作

(1)验证(Verify),验证文件格式、元数据、字节码和符号引用,以保证被加载类的准确性;

(2)准备(Prepare),为静态变量分配内存并初始化为默认值。

(3)解析(Resolve),解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。

  1. 初始化:初始化(Initialize)阶段所做的工作就是对类的静态成员变量和静态方法进行初始化赋值或调用。

比如上面的静态变量age初始化之后的值变为了10。

在装载阶段的第(2),(3)步可以发现有运行时数据区,堆,方法区等名词,那么究竟什么是“运行时数据区”,它有哪些结构构成?

5、什么是JVM运行时数据区?及其逻辑结构

“运行时数据区”是JVM在执行Java程序的过程中出于内存管理方面的目的,在设计上把内存分为若干个不同的区域。这些区域有着各自的用途,有的区域生命周期跟虚拟机一样,随着虚拟机进程的启动而存在,伴随这虚拟机的进程结束而消亡。而有些区域则依赖用户线程的启动和结束而建立和销毁。具体如下图:

  1. 方法区(Method Area):
    (1)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据;

(2)方法区是各个线程共享的内存区域,在虚拟机启动时创建,因为同一个class类信息只需要加载一份就够了;

(3)java虚拟机规范中把方法区描述为堆内存的一个逻辑部分,但它有另外一个别名叫“非堆”,用于与java堆区分开来。在JDK8之前方法区叫做Perm space,在JDK8及以后叫做Metaspace(即元数据区)。

  1. 堆(Heap):Java堆是被所有线程共享,虚拟机启动时创建,此内存区域唯一的目的就是存放对象实例,在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展和逃逸分析技术逐渐成熟,栈上分配,标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也就变得不那么绝对了。
  2. 虚拟机栈(Java Virtual Machine Stacks):虚拟机栈是线程私有的或者说是独有的,随着线程的创建而创建。一个线程的运行状态(正在调用哪个方法),就是由这个线程对应的虚拟机栈来保存的。

每一个被线程执行的方法,为虚拟机栈中的一个栈帧,调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。如下图解:

  1. 程序计数器(The Pc Register):我们都知道一个JVM进程中有多个线程在执行,而线程中的内容是否能够拥有执行权,是根据CPU调度来的。假如线程A正在执行到某个地方,突然失去了CPU的执行权,切换到线程B了,然后当线程A再获得CPU执行权的时候,怎么能继续执行呢?这就是需要在线程中维护一个变量,记录线程执行到的位置,这就是程序计数器。
  2. 本地方法栈(Native Method Stacks):本地方法栈与虚拟机栈所发挥的作用非常相似,他们之间的区别不过是虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈则为虚拟机中使用到的native方法服务。即如果当前线程执行的方法是Native类型的,这些方法就会在本地方法栈中执行。

总结一下,就JVM的设计规范,从使用用途角度JVM的内存大体的分为:线程私有内存区 和 线程共享内存区。

线程私有内存区在类加载器编译某个class文件时就确定了执行时需要的“程序计数器”和“虚拟栈帧”等所需的空间,并且会伴随着当前执行线程的产生而产生,执行线程的消亡而消亡,因此“线程私有内存区”并不需要考虑内存管理和垃圾回收的问题。

线程共享内存区在虚拟机启动时创建,被所有线程共享,是Java虚拟机所管理内存中最应该关注的和最大的一块。

那么JVM内存模型是如何设计的?JVM又是如何进行内存管理(也就是垃圾回收)的?垃圾回收算法有哪些?目前常用的垃圾回收器又有哪些?我会在下篇文章跟您共同解答这些问题。

作者:宜信技术学院 谭文涛

相关文章
|
4月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
430 3
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
65 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
20天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
1月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
46 3
|
1月前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
1月前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
60 0
|
4月前
|
存储 算法 安全
(八)JVM成神路之GC分区篇:G1、ZGC、ShenandoahGC高性能收集器深入剖析
在《GC分代篇》中,我们曾对JVM中的分代GC收集器进行了全面阐述,而在本章中重点则是对JDK后续新版本中研发推出的高性能收集器进行深入剖析。
167 12
|
4月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
106 8
|
3月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
3月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用