JVM
JVM
Gene Xu
个人博客:https://blog.xujun.pro;个人公众号:Sakura动漫ACG
展开
-
Performance Tuning -- 09 -- Btrace应用示例
这里主要展示些 Btrace 相关的应用示例一、拦截简单参数监控方法@RestControllerpublic class HelloController { /** * 拦截简单参数 */ @GetMapping(value = "/arg/simple/{name}") public String argSimple(@PathVariable("name") String name) { return "Hello " +原创 2020-05-27 10:54:04 · 177 阅读 · 0 评论 -
Performance Tuning -- 08 -- Btrace的简单应用
当生产环境出现问题时,我们可能会需要获取程序运行时的相关参数来进行分析,而常规方法需要修改代码,将相关参数输入到日志中,再将项目重新发布到生产环境。不过要是这么做,一是十分繁琐,二是风险较大,此时 Btrace 就登场了一、安装 Btrace首先我们先上官网 (btrace) 下载 Btrace,这里我下载的是 1.3.11.3 版本接着配置 Btrace 环境变量 (替换成自己的安装路径)环境变量变量值JAVA_HOMED:\MySoftware\Java\jdk原创 2020-05-26 23:43:25 · 210 阅读 · 1 评论 -
Performance Tuning -- 07 -- Btrace常用配置解析
Btrace (Byte Trace) 是 Sun 公司推出的一款 Java 动态、安全追踪 (监控) 工具,可以在不停机的情况下监控系统运行情况,并且做到最少的侵入,占用最少的系统资源,也就是说 Btrace 可以动态地向目标应用程序的字节码注入追踪代码Btrace 脚本其实就是一个普通的 Java 类,只不过用 @Btrace 注解进行了修饰,一个 Btrace 脚本可以包含一个或多个拦截方法,需要注意的是,拦截方法必须用 public static void 进行修饰,否则启动 Btrace 脚本时原创 2020-05-26 23:22:56 · 174 阅读 · 0 评论 -
Performance Tuning -- 06 -- 使用JVisualVM监控远程Java进程
JVisualVM 除了监控本地的 Java 进程外,还可以监控远程的 Java 进程一、使用 JMX 远程监控 Tomcat修改 catalina.sh修改 Tomcat 的启动脚本,将 JMX 的相关参数添加进 Tomcat 的启动命令中,并启动 TomcatJAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9997 -Dcom.sun.manageme原创 2020-05-25 23:31:18 · 194 阅读 · 0 评论 -
Performance Tuning -- 05 -- JVisualVM的使用
在之前我们提到了,当遇到内存溢出、程序卡顿、CPU 占用率过高等情况下,我们可以通过 jmap、jstack 等 JDK 自带的命令通过命令行来进行分析,不过命令行操作不是很直观,那么有没有可视化的监控工具呢,答案是肯定的,这里我们就来了解下 JDK 自带的监控管理工具 JVisualVM一、功能概览JVisualVM 位于 JDK 的 bin 目录下,它可以监控本地所有的 Java 进程,这里我们启动之前测试内存溢出和死循环、死锁用到的项目应用程序如上所示,本地标签中展示了本地所有的原创 2020-05-25 22:49:27 · 181 阅读 · 0 评论 -
Performance Tuning -- 04 -- jstack分析死循环和死锁
这里我们通过 jstack 来分析下死循环和死锁的问题一、死循环示例CpuController.java@RestControllerpublic class CpuController { @GetMapping(value = "/loop/{data}") public String loop(@PathVariable("data") String data) { while (true) { int index = data.原创 2020-05-24 23:38:57 · 271 阅读 · 0 评论 -
Performance Tuning -- 03 -- jmap+MAT 分析内存溢出
这里我们通过 jmap 和 MAT 来分析下内存溢出的问题一、堆内存溢出User.java@Datapublic class User { private int id; private String name; public User(int id, String name) { this.id = id; this.name = name; }}MemoryController.java@RestControl原创 2020-05-24 22:41:11 · 255 阅读 · 0 评论 -
Performance Tuning -- 02 -- JVM监控和调优常用命令
在生产环境下,程序或多或少都会碰到卡顿、CPU 占用率高等问题,而因为是生产环境,我们不能随意地关闭或重启程序。此时,我们可以通过 JDK 自带的状态监控命令和图形化管理工具来定位和解决问题,并作出相应的优化一、jps (JVM Process Status Tool)用于列出正在运行的虚拟机进程,并显示虚拟机执行主类 (main() 方法所在的类) 名称以及虚拟机进程 ID命令格式jps [options] <hostid>格式说明参数名含义o原创 2020-05-24 17:14:10 · 308 阅读 · 0 评论 -
Performance Tuning -- 01 -- JVM常用命令
这里我们主要来了解下 JVM 中的常用命令一、JVM 参数分类标准参数 (-)在 JVM 的各个版本中基本不变,相对比较稳定非标准参数 (-X)在 JVM 的各个版本中可能会变,但变化的较小非稳定参数 (-XX)在 JVM 的各个版本中相对不稳定,主要用于 JVM 的性能调优以及 Debug,分为以下两类Boolean 类型格式含义-XX:[±] 表示启用 (+) 或者禁用 (-) name 属性key-value 类型.原创 2020-05-21 11:21:11 · 344 阅读 · 0 评论 -
Memory Model -- 14 -- Java内存模型
在计算机中,绝大多数的运算任务不可能只靠处理器的计算就能完成,处理器需要与内存进行交互,如:读取运算数据、存储运算结果等,这个 I/O 操作是很难消除的 (无法仅靠寄存器来完成所有运算任务)由于计算机的存储设备与处理器的运算速度有着几个数量级的差距,所以在现代计算机系统中都不得不加入一层或多层读写速度尽可能接近处理器运算速度的高速缓存 (Cache) 来作为内存与处理器之间的缓冲:将运算需要使用的数据复制到缓冲中,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样处理器就无须等待缓慢的内存读写了原创 2020-05-18 15:38:21 · 262 阅读 · 0 评论 -
Memory Model -- 13 -- volatile的基本概念
volatile 是 Java 虚拟机提供的最轻量级的同步机制,其具有以下两项特性保证被 volatile 修饰的共享变量对所有线程都是可见的,所谓可见性,是指当一个线程修改了被 volatile 修饰的共享变量时,新值对于其他线程来说是可以立即得知的禁止指令重排序优化一、volatile 的可见性volatile 变量在各个线程的工作内存中不存在一致性的问题,但是在 Java 中运算操作符并非是原子操作,因此 volatile 变量的运算在并发情况下是线程不安全的线程不安全原创 2020-05-18 15:32:27 · 293 阅读 · 0 评论 -
Memory Model -- 12 -- 对象的访问定位
在 Java 程序中,我们需要通过 reference 引用 (存储于虚拟机栈的局部变量表中) 来操作堆上的具体数据reference 类型在 Java 虚拟机规范中只规定了它是一个指向对象的引用,并没有定义这个引用应该通过什么方式区定位、访问到堆中对象的具体位置,所以对象访问的方式是由虚拟机自行实现的,目前主流的访问方式主要有使用句柄和直接指针两种一、使用句柄当使用句柄访问时,Jav...原创 2020-04-27 11:25:42 · 189 阅读 · 0 评论 -
Memory Model -- 11 -- 对象的内存分布
对象在堆内存中的存储布局可以划分为三个部分:对象头 (Header)、实例数据 (Instance Data) 和对齐填充 (Padding)一、对象头 (Header)Mark WordMark Word 用于存储对象自身的运行时数据,如:哈希码 (HashCode)、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等由于对象头信息是与对象自身定义的数...原创 2020-04-27 11:21:37 · 229 阅读 · 0 评论 -
Memory Model -- 10 -- 对象的创建
众所周知,通过 new 关键字,我们就可以轻松地创建一个 Java 对象,但在 Java 虚拟机中,对象的创建可并不如此简单,让我们来一起了解下这整个过程一、对象的创建过程当 Java 虚拟机遇到一条字节码 new 指令时,会先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过,如果没有,则必须先执行相应的类加载过程...原创 2020-04-27 10:56:08 · 224 阅读 · 0 评论 -
Memory Model -- 09 -- 直接内存
直接内存 (Direct Memory) 并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域,而是可以使用 Native 函数库直接分配的堆外内存,也可称为本地内存 (Native Memory)一、相关定义在 JDK4 中新加入了 NIO (New Input/Output) 类,引入了一种基于通道 (Channel) 与缓冲区 (Buffer) 的 I/...原创 2020-04-27 10:42:31 · 205 阅读 · 0 评论 -
Garbage Collection -- 08 -- 老年代垃圾收集器
再了解完新生代的垃圾收集器后,我们再来了解下老年代的垃圾收集器一、Serial Old 收集器Serial Old 收集器是 Serial 收集器的老年代版本,它同样是一个单线程收集器,采用标记-整理算法在程序启动的时候,通过使用 -XX:UseSerialOldGC 参数来指定老年代使用 Serial Old 收集器来进行回收单线程,进行垃圾收集时,必须暂停所有工作线程...原创 2020-04-13 17:19:22 · 227 阅读 · 0 评论 -
Garbage Collection -- 07 -- 新生代垃圾收集器
在了解新生代的垃圾回收器之前,我们先来了解下 Java 虚拟机的运行模式Java 虚拟机有两种运行模式,分别是 Server 和 ClientClient 模式启动速度较快,Server 模式启动较慢当启动稳定后,Server 模式程序运行速度要比 Client 模式快,这是由于 Server 模式启动的 JVM 采用的是重量级的虚拟机,对程序采用了更多的优化;而 Client 模式...原创 2020-04-13 15:49:38 · 193 阅读 · 0 评论 -
Garbage Collection -- 06 -- HotSpot 的算法实现
之前我们了解了对象存活判定算法以及垃圾回收算法,而在 HotSpot 虚拟机上实现这些算法时,必须对算法的执行效率有严格的考量,才能保证虚拟机高效运行一、枚举根节点在可达性算法中,可作为 GC Roots 的节点主要在全局性的引用 (例如常量或类静态属性) 与执行上下文 (例如栈帧中的本地变量) 中,如果逐个检查这里面的引用,那么必然会消耗很多时间另外,可达性分析对执行时间的敏感还...原创 2020-04-13 10:38:47 · 166 阅读 · 0 评论 -
Garbage Collection -- 05 -- 分代收集算法 (Generational Collection)
接下来我们再来具体了解下分代收集算法 (Generational Collection)分代收集算法的 GC 分为两种,一种是 Minor GC (新生代 GC),另一种是 Full GC (老年代 GC,也称为 Major GC)新生代 GC (Minor GC)新生代 GC (Minor GC),是指发生在新生代中的垃圾收集动作新生代几乎是大多数 Java 对象出生的地方,...原创 2020-04-12 19:01:05 · 354 阅读 · 0 评论 -
Garbage Collection -- 04 -- 垃圾回收算法
接着我们再来了解下 Java 虚拟机中的垃圾回收算法,主要有以下几种:标记-清除算法 (Mark-Sweep)、复制算法 (Copying)、标记-整理算法 (Mark-Compact)、分代收集算法 (Generational Collection)一、标记-清除算法 (Mark-Sweep)该算法分为两个阶段:标记和清除,该算法首先从根集合开始扫描,对存活的对象进行标记 (使用可达性分...原创 2020-04-12 17:07:00 · 307 阅读 · 0 评论 -
Garbage Collection -- 03 -- Java中的四种引用
无论是通过引用计数算法判断对象的引用数量,还是通过可达性分析算法判断对象的引用链是否可达,判定对象是否存活都与 “引用” 有关在 JDK2 之前,Java中关于引用的定义很传统:如果 reference 类型的数据中存储的数值代表的是另一块内存的起始地址,就称这块内存代表着一个引用。这种定义很纯粹,但是太过狭隘,一个对象在这种定义下只有被引用或者没有被引用两种状态,对于如何描述一些 “食之无味,...原创 2020-04-10 15:07:45 · 129 阅读 · 0 评论 -
Garbage Collection -- 02 -- finalize()方法的作用
之前提到在可达性分析算法中,引用链不可达的对象将会被回收,不过这些对象并不是一定会被回收,可能会被 finalize() 方法赋予一次重生的机会 (仅有一次,因为一个对象的 finalize() 方法最多只会被系统自动调用一次)要真正宣告一个对象死亡,至少要经历两次标记过程第一次标记如果对象在进行可达性分析算法后发现没有与 GC Roots 相连接的引用链,那它将会被第一次标记并且进...原创 2020-04-08 22:29:26 · 176 阅读 · 0 评论 -
Garbage Collection -- 01 -- 判断对象是否存活
目前内存的动态分配与内存回收技术已经相当程数,一切看起来都进入了 “自动化” 时代,那么为甚么我们还要去了解 GC 和内存分配呢?答案很简单:当我们需要排查各种内存溢出、内存泄漏的问题时;当垃圾收集称为系统达到更高并发量的瓶颈时,我们就需要对这些 “自动化” 的技术实施必要的监控和调节内存溢出 (out of memory):是指程序在申请内存时,没有足够的空间供其使用内存泄漏 (m...原创 2020-04-08 16:02:40 · 199 阅读 · 0 评论 -
Memory Model -- 08 -- 不同JDK版本之间 String.intern() 方法的区别
对于 String 类的 intern 方法,平常了解的不是很多,最近在学习的过程中接触到了这个方法,特地来整理记录一下一、区别JDK6 及之前的版本中当调用 intern 方法时,如果字符串常量池 (StringTable) 中存在该字符串对象,则返回字符串常量池中该字符串对象的引用当调用 intern 方法时,如果字符串常量池 (StringTable) 中不存在该字符...原创 2019-12-12 22:32:11 · 366 阅读 · 0 评论 -
Memory Model -- 07 -- Java中的常量池详解
最近在学习 Java 虚拟机的相关知识时,出现了好几种常量池的概念,被弄的很模糊,于是上网查了下资料,再结合自己的看法,总结了一下:在 java 的内存分配中,总共存在三种常量,分别是:字符串常量池、Class 文件常量池、运行时常量池一、字符串常量池 (String Constant Pool)在 HotSpot 虚拟机中,实现字符串常量池的是一个名为 StringTable 的类,...原创 2019-12-01 21:28:23 · 168 阅读 · 0 评论 -
Memory Model -- 06 -- 运行时数据区(五、方法区)
一、方法区 (Method Area)方法区 (Method Area) 与 Java 堆一样,是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据当方法区无法满足内存分配的需求时,将会抛出 OutOfMemoryError 异常二、永久代与元空间在 Java 虚拟机规范中,只规定了方法区的概念及其作用,但并没有规...原创 2019-11-25 22:57:13 · 210 阅读 · 0 评论 -
Memory Model -- 05 -- 逃逸分析
之前提到了逃逸分析技术,它可能会导致对象实例不一定被分配到堆内存上,现在让我们一起来看看是逃逸分析技术一、即时编译器 (JIT)在这之前,我们首先来认识下 JTT,在部分的商用虚拟机中,Java 程序是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为 “热点代码” (Hot Spot Code)为了提高热点代码的执行效率,在运行时,虚拟...原创 2019-10-30 16:57:03 · 198 阅读 · 0 评论 -
Memory Model -- 04 -- 运行时数据区(四、堆)
一、Java 堆 (java Heap)对于大多数应用来说,Java 堆 (Java Heap) 是 Java 虚拟机所管理的内存中最大的一块,Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存这一点在 Java 虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配,但是随着 JIT ...原创 2019-10-30 15:00:04 · 215 阅读 · 0 评论 -
Memory Model -- 03 -- 运行时数据区(三、本地方法栈)
一、本地方法栈 (Native Method Stack)本地方法栈 (Native Method Stack) 与虚拟机栈发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行 Java 方法 (也就是字节码) 服务,而本地方法栈则为虚拟机使用到的 Native 方法服务在虚拟机规范中对本地方法栈中方法使用的语言、使用方式和数据结构并没有强制规定,因此具体的虚拟机可以...原创 2019-10-29 21:49:21 · 311 阅读 · 1 评论 -
Memory Model -- 02 -- 运行时数据区(二、虚拟机栈)
一、Java 虚拟机栈 (Java Virtual Machine Stacks)与程序计数器一样,Java 虚拟机栈 (Java Virtual Machine Stacks) 也是线程私有的,它的生命周期与线程一样。虚拟机栈描述的是 Java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧 (Stack Frame:栈帧是方法运行时的基础数据结构) 用于存储局部变量表、操...原创 2019-10-27 23:00:51 · 224 阅读 · 0 评论 -
Memory Model -- 01 -- 运行时数据区(一、 程序计数器)
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域各有各的用途、创建及销毁时间,现在让我们来详细地了解下 Java 的内存模型一、程序计数器 (Program Counter Register)程序计数器 (Program Counter Register) 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器在虚...原创 2019-10-17 23:45:27 · 335 阅读 · 1 评论 -
Class Loading -- 07 -- forName()和loadClass()的区别
类的加载方式可分为隐式加载和显示加载两种隐式加载:new对于隐式加载而言,当程序在运行过程中,遇到通过 new 方式来生成对象时,会隐式调用类加载器,加载对应的类到虚拟机中显示加载:forName()、loadClass():对于现实加载而言,当我们获取到 Class 对象之后,需要调用 Class 对象的 newInstance() 方法来生成对象实例forNam...原创 2019-10-15 22:31:45 · 183 阅读 · 0 评论 -
Class Loading -- 06 -- 破坏双亲委派模型
双亲委派模型并不是一个强制性的约束模型,而实 Java 设计者推荐给开发者的类加载器实现方式,在 Java 的世界中大部分的类加载器都遵循这个模型,但也有例外,到目前为止,双亲委派模型主要出现过三次较大规模的 “被破坏” 情况一、第一次被破坏发生在双亲委派模型出现之前,双亲委派模型在 JDK2.0 之后才被引入,为了向前兼容 JDK1.0 已经存在的自定义类加载器,JDK2.0 之后的...原创 2019-10-15 21:42:58 · 238 阅读 · 0 评论 -
Class Loading -- 05 -- 双亲委派模型
不同的类加载器加载类的方式和路径各有不同,为了实现分工,各自负责各自的区块,使得逻辑更加明确,我们才会有这么多种相互共存的类加载器,为了让它们之间相互协作,形成一个整体,我们需要引入一个模型:双亲委派模型一、双亲委派模型自下而上检查类是否已经被加载,自上而下尝试加载类双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,且这些类加载器之间的父子关系一...原创 2019-10-15 20:24:03 · 179 阅读 · 0 评论 -
Class Loading -- 04 -- JVM类加载机制(三、类加载器)
接着我们再来详细地了解下虚拟机中的类加载器一、类与类加载器对于任意一个类,都需要由加载它的类加载器和这个类本身以通确立其在 Java 虚拟机中的唯一性每一个类加载器,都拥有一个独立的类名称空间,通俗地讲:即比较两个类是否 “相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,不然即使这两个类来源于同一个 Class 文件,被同一个虚拟机加载,但只要加载它们的类加载器不同...原创 2019-10-14 09:16:46 · 169 阅读 · 0 评论 -
Class Loading -- 03 -- JVM类加载机制(二、类加载过程)
接着我们再来详细地了解下虚拟机中类加载的全过程,主要是加载、验证、准备、解析、初始化这五个阶段所执行的具体动作一、加载 (Loading)在加载阶段,虚拟机需要完成以下三件事通过一个类的全限定名来获取定义此类的二进制字节流从 ZIP 包中读取,是日后 JAR、EAR、WAR 格式的基础从网络中获取,这种场景最典型的应用就是 Applet运行时计算生成,这种场景使...原创 2019-10-13 21:35:20 · 205 阅读 · 0 评论 -
Class Loading -- 02 -- JVM类加载机制(一、类加载时机)
虚拟机将描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这一过程称之为类加载机制在Java中,类型的加载、连接和初始化过程都是在程序运行期间完成的,依赖于运行期动态加载和动态连接这两个特点,实现了 Java 可以动态扩展的语言特性一、类的生命周期类的生命周期如上所示,其中加载、验证、准备、初始化和卸载这五个阶段...原创 2019-10-09 21:33:03 · 174 阅读 · 0 评论 -
Class Loading -- 01 -- JVM基本架构
JVM 即 Java Virtual Machine (Java 虚拟机),它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机的功能来实现的在引入 JVM 后,Java 语言实现了平台无关性 (即跨平台性),Java 源码只需要编译一次,就不用在其他操作平台上再次编译了,JVM 屏蔽了与具体操作平台相关的信息,使得 Java 编译程序只需要生成在 JVM 上运行的目标代码 (...原创 2019-10-09 15:31:58 · 197 阅读 · 0 评论