![](https://img-blog.csdnimg.cn/97b11f49505e4215bd4c347761721f8f.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
深入理解JVM
文章平均质量分 96
从JVM的整体架构出发,探究它的运行机制以及性能调优
sermonlizhi
行百里者半九十
展开
-
深入理解Synchronized(一)
一、简介JMM(Java Memory Model,Java内存模型)规范定义Java的共享内存模型,但共享内存模型随之带来的就是共享变量的线程安全问题,对JMM的理解可以参看《Java 内存模型》这篇文章。为了保证多线程对共享变量的互斥操作,Java提供了两大类型的方案,即阻塞式和非阻塞式的解决方案。阻塞的方式有Synchronized关键字和Lock锁,非阻塞的方式使用原子变量(CAS+自旋)。而在Java中,互斥和同步都可以通过Synchronized来实现,但它们还是有区别的:互斥是保证临界原创 2022-01-10 11:25:32 · 844 阅读 · 2 评论 -
深入理解Synchronized(二)
一、对象的内存布局在Hotspot虚拟机中,对象在内存中的布局分为三块区域:对象头(Header)、实例数据(Instance Data)和对其填充(Padding)。对象头:比如hash码,对象所属的年代,对象锁,锁状态标志,偏向锁(线程)ID,偏向时间,数组长度(数组对象才有)等实例数据:存放类的属性数据信息,包括父类的属性信息对齐填充:由于Hotspot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是任何对象的大小都必须是8字节的整数倍。对象头已经被精心设计成正好是8原创 2022-01-10 20:20:05 · 1046 阅读 · 1 评论 -
深入理解Synchronized(三)
在前面两篇关于Synchronized的文章中,已经简单介绍了Synchronized中管程模型、锁对象如何保存锁状态以及偏向锁和轻量级锁基本的锁状态转换,这篇文章更加深入介绍Synchronized中相关锁的底层原理、锁状态转换以及锁优化等内容一、轻量级锁底层原理1.1 加锁逻辑轻量锁的锁对象与线程锁记录之间的关系如下图所示:线程每次加锁,都会在线程的栈帧中分配一块锁记录的空间,锁记录里面包含了锁对象的Mark Word(displaced word)和指向锁对象的指针,而锁对象的对象头里面的p原创 2022-01-15 16:24:11 · 1136 阅读 · 1 评论 -
JVM类加载机制
在Java中,通常会说万物皆是对象,即便是一个编译后的.class文件,它也需要变成一个对象,才能在Java中使用,而将.class文件变成对象的过程就是类加载机制。这篇文章主要介绍Java的类加载机制的原理,包括常用的类加载器和设计原理。一、类加载过程以下面的简单程序为例:public class ClassLoadTest { public static void main(String[] args) { System.out.println("Hello Word")原创 2022-05-14 11:34:15 · 1363 阅读 · 0 评论 -
JVM内存模型
Java在诞生之初就提出了"Write once,Run Anywhere"的口号,而这些都得益于JVM(Java Vritual Machine),可以提前在不同的运行环境(linux或windows等)上安装JDK之后,就可以让同一份代码在任何地方运行了。而这里的JDK(Java Development Kit)是Java语言、Java虚拟机和Java类库的统称。一、JDK体系结构与Java跨平台特性1.1 JDK体系结构JDK是一个非常庞大的体系,里面包含了JVM、Java SE API(核心类原创 2022-05-14 21:16:34 · 18247 阅读 · 2 评论 -
JVM内存分配机制
Java虚拟机最重要的工作就是如何给对象分配内存空间,以及通过GC如何回收已经不再使用的内存空间。这篇文章主要介绍JVM中的Java对象是创建过程、对象内存的分配机制以及对象内存的回收机制。一、对象的创建在前面的文章《JVM类加载机制》中讲过,JVM中所有对象的创建,都需要先将对应的.class文件加载进内存,所以JVM中通常一个对象的创建包含了如下几个步骤:1.1 检查类是否加载当JVM执行到new字节码指令时,首先会去运行时常量池检查该指令指定的参数能够找到对应类的符号引用,并检查这个符号引用原创 2022-05-17 13:54:34 · 3278 阅读 · 1 评论 -
GC算法与GC收集器
Java相比于C++这样语言,除了跨平台的特性外,最突出的特点就是垃圾回收机制。C++的开发人员还需要手动分配和回收内存,但JVM直接承担起了垃圾回收的重任,开发人员可以专注于业务开发,不需要再去关心复杂的内存回收。JVM的垃圾收集包含了两部分内容:垃圾收集算法与垃圾收集器,这两者是理论与实践的关系。前者提供理论依据,后者是对理论的实现。在《JVM内存分配机制》这篇文章中介绍过了堆空间是按照新生代和老年代来划分的,这是因为根据对象的不同生命周期划分不同的区域后,垃圾回收时可以根据各个区域的特性,采用不同原创 2022-05-18 19:45:39 · 1396 阅读 · 1 评论 -
详解G1垃圾收集器
G1(Garbage-First)作为继CMS之后新一代面向服务器的垃圾收集器,它已经不再严格按照之前老年代和新生代的划分来进行垃圾收集,即它是一个老年代和新生代共用的垃圾收集器。G1更多是在多处理器(或多核)以及大内存的机器上发挥优势,在满足指定GC停顿时间要求的同时,还具备高吞吐量的能力。这篇文章主要从G1的设计理念和垃圾回收过程来详细介绍。一、设计思想在《GC收集算法与GC收集器》这篇文章中介绍了JVM中经典的垃圾收集器,这些垃圾收集器的共性是在整个垃圾收集过程中,一定会发生Stop The原创 2022-05-19 17:15:37 · 11100 阅读 · 3 评论 -
详解ZGC垃圾收集器
从G1垃圾收集器开始,后面的垃圾收集器都不再将堆按照新生代和老年代作为整体进行回收,都采用了局部收集的设计思想。可能是由于G1作为第一代局部收集的垃圾收集器,所以它继续保留了新生代和老年代的概念,笔者认为从局部收集和分区的内存布局来看,按代收集理论已经没有什么特别存在的必要了。一、ZGC的设计思路1.1 ZGC的内存布局新一代的垃圾收集器ZGC(Z Garbage Collector)就完全抛弃了按代收集理论,它与G1一样将内存划分成各个小的区域的,但与G1有所不同的是,ZGC的各个内存区域称为页面原创 2022-05-20 18:53:00 · 4499 阅读 · 1 评论 -
JVM调优工具(一)
前面的文章已经介绍了JVM对象创建时的内存分配、类加载机制以及垃圾收集等核心的内容,对JVM的内存模型基本有了比较完整的了解。但这些都只是理论,当程序运行遇到问题时,更多的时候是需要根据现象然后结合理论才能做出合理的判断。而JDK就提供了很多的工具来帮助开发人员获取程序运行时的各种数据,包括异常堆栈、JVM运行日志、GC日志、线程快照文件、堆转储快照文件等等。这篇文章就借助部分常用工具,结合具体的应用程序来查看程序运行过程中的各种数据,对这些数据进行分析,继而更好的调整JVM参数。一、基础工具1.1原创 2022-05-21 19:16:43 · 1614 阅读 · 0 评论 -
JVM调优工具(二)
上一篇文章介绍了JDK自带的一些可以查看JVM各种参数的工具,但在linux服务器上没有可视化的工具使用,如果通过远程连接到linux服务器还需要启动jstatd和JMX等,是存在一些安全隐患的。但JDK自带的一些基本命令行工具虽然可以查看内容,但也不是特别方便,不能够直观的看到JVM内部的情况,于是阿里巴巴在2018年9月推出了一款Java诊断工具Arthas,它支持JDK6+,采用命令行的交互方式,可以很方便的定位和诊断线上程序运行的问题。Arthas可以看作是对JDK工具包的一种再次封装,同时提供原创 2022-05-23 16:49:32 · 505 阅读 · 0 评论 -
详解JVM的常量池
在《JVM类加载机制》和《JVM内存模型》这两篇文章都对常量池和运行时常量池做了不少介绍,这篇文章再次聚焦常量池,搞清楚常量池到底都有什么。一、静态常量池与运行时常量池静态常量池也可以称为Class常量池,也就是每个.java文件经过编译后生成的.class文件,每个.class文件里面都包含了一个常量池,因为这个常量池是在Class文件里面定义的,也就是.java文件编译后就不会在变了,也不能修改,所以称之为静态常量池。以下面的Test.java文件为例:public class Test {原创 2022-05-24 13:36:29 · 5984 阅读 · 6 评论 -
详解JVM的即时编译
JVM之所以拥有强大的生态,是因为它是跨语言性的,JVM只识别字节码文件,不论是什么语言编写的代码,只要经过编译后能生成.class的字节码文件,JVM都可以进行解析。当然这些字节码文件都要符合JVM对于Class文件的格式定义,不能随便一个文件将后缀改成.classs就能行的。像Groovy、Kotlin、Scala等语言,它们编译后生成的都是字节码文件,所以它们可以在JVM上运行。字节码文件的内容除了一些常量池的一些信息外,其他基本都是每个方法中语句对应的字节码指令,像下面这样包含了部分main(原创 2022-05-24 18:58:56 · 950 阅读 · 0 评论 -
新一代虚拟机GraalVM
在JDK10以前,能进行性能优化的即时编译器只有C2,但C2编译器的代码据说已经变得非常庞大且臃肿,同时伴随着云原生时代的到来,Java这种需要借助JDK才能运行的语言就显得格外臃肿,于是就有了Graal编译器的诞生,Graal编译器提供了非常强悍的能力,所以通常把Graal编译器与HotSpot合称为新一代的虚拟机——GraalVM。GraalVM是一个高性能JDK发行版,旨在加速用Java和其他语言编写的应用程序的执行,并支持JavaScript、Ruby、Python和许多其他流行语言。从上面的原创 2022-05-25 18:32:57 · 1435 阅读 · 2 评论