JVM结构化体系

目录

目录

1.JVM 简介

1.1. 如何理解 JVM 呢?

 1.2. 市场主流 JVM 分析?

1.3. 为什么要学习 JVM?

1.4. 字节码底层是如何执行呢?

如何理解 JIT 呢?

为什么 JVM 中解释执行与编译执行的并存(混合模式)?

1.5. 如何理解 JVM 的运行模式?

如何查看现在 JVM 的工作模式?

2.JVM 体系结构

2.1. JVM 的产品架构是怎样的?

2.2. JVM 运行时内存结构是怎样的?

2.2.1. JVM 线程共享区应用分析

1. Heap (堆内存):

2. Method Area (方法区)

2.2.2. JVM 线程私有区应用分析

1. Program Counter Register (程序计数器)

2. Stack Area (虚拟机栈区)

3. Native Stack Area (本地方法栈)

 3.JVM 应用参数分析

3.1. 如何理解 JVM 中的内存溢出?

代码演示:堆内存溢出

代码演示:元数据内存溢出(JDK8)

3.2. JVM 工具应用分析篇

3.2.1. 命令行工具篇

1. Jps [options] [hostid] (hostid 为 ip 或域名地址)

2. jmap -heap pid

3. jstack 用于生成 java 虚拟机当前时刻的线程快照


1.JVM 简介

1.1. 如何理解 JVM 呢?

JVM(Java Virtual Machine) 是:
1) JAVA 平台的一部分,是一种能够运行 Java bytecode 的虚拟机。
2) 是硬件计算机的抽象 ( 虚构 ) 实现,可以解释执行 JAVA 字节码。
3) 是实现 JAVA 跨平台运行的基石。

 1.2. 市场主流 JVM 分析?

JVM 是一种规范基于这种规范,不同公司就对此规范做了具体实现,例如市场上
的一些主流 JVM 如下:
1. JRockit VM (BEA 公司研发,后在 2008 年由 Oracle 公司收购 )
2. HotSpot VM (Sun 公司研发,后在 2010 年由 Oracle 公司收购 )
3. J9 VM IBM 内部使用)
说明: HotSpot 目前是应用最官方,最主要的一款 JVM 虚拟机

1.3. 为什么要学习 JVM

深入理解 JVM 可以帮助我们从平台角度提高解决问题的能力,例如:
1) 有效防止内存泄漏( Memory leak
2) 优化线程锁的使用 (Thread Lock) 齐雷 qilei@tedu.cn
1-4
3) 科学进行垃圾回收 (Garbage collection)
4) 提高系统吞吐量 (throughput)
5) 降低延迟 (Delay) ,提高其性能 (performance)

1.4. 字节码底层是如何执行呢?

JAVA 源程序编译,执行过程如下图所示:

在主流的 JVM (例如 HotSpot )中 , class 文件翻译成机器码执行时提供了两
种方式,如下图所示:1
其中:
1) 热点代码: 一般泛指循环或高频使用的方法。
2) 解释执行器:负责逐条将字节码翻译成机器码并执行。
3) 编译执行器:负责即时编译 (Just-In-Time compilation,JIT) 执行。

如何理解 JIT 呢?

JIT( 即时编译 ) 是用来提高 java 程序运行效率的一种技术 , 基于这种技术,可以
字节码编译成平台相关的原生机器码,并进行各个层次的优化,这些机器码会被
缓存起来,以备下次使用。

为什么 JVM 中解释执行与编译执行的并存(混合模式)?

解释器与编译器两者各有优势,当程序需要迅速启动和执行的时候,解释器可以
首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,
即时编译( JIT )逐渐发挥作用,它可以对反复执行的热点代码以方法为单位进
行即时编译,可以获取更高的执行效率。但是如果 JIT 对每条字节码都进行编
译,缓存 ( 缓存的指令是有限的 ) ,会增加开销。所以当程序运行环境中内存资源
限制较大(如部分嵌入式系统中),可以使用解释器执行节约内存,反之可以使
用编译执行来提升效率。

1.5. 如何理解 JVM 的运行模式?

JVM 有两种运行模式 Server Client。两种模式的区别在于,Client

式启动速度较快, Server 模式启动较慢;但是启动进入稳定期之后 Server
式的程序运行速度比 Client 要快很多。这是因为 Server 模式启动的 JVM 采用
的是重量级的虚拟机,对程序采用了更多的优化;而 Client 模式启动的 JVM
用的是轻量级的虚拟机。所以 Server 启动慢,但稳定后速度比 Client 远远要
快。

如何查看现在 JVM 的工作模式?

说明:现在 64 位的 jdk 中默认都是 server 模式。当虚拟机运行在 -client
模式的时候 , 使用的是一个代号为 C1 的轻量级编译器 , -server 模式启动的
虚拟机采用相对重量级 , 代号为 C2 的编译器 .c1 c2 都是 JIT 编译器, C2 C1 编译器编译的相对彻底 , 服务起来之后 , 性能更高 .

2.JVM 体系结构

2.1. JVM 的产品架构是怎样的?

JVM Java Hotspot Architecture :主要分为三大部分:
1) 类加载系统 ( ClassLoader System ) :负责加载类到内存
2) 运行时数据区 ( Runtime Data Area ):负责存储数据信息
3) 执行引擎 ( Execution Engine : 负责调用对象执行业务

2.2. JVM 运行时内存结构是怎样的?

JVM 启动运行 Class 文件时会对 JVM 内存进行切分,我们可以将其分为线程共

享区和线程独享区。如下图所示 .
其运行时内存详细架构如下:
备注:
 
1.在 JDK8 中持久代 (Permanent Generation)部分数据移到了元数据 ( Metaspace ),在 JDK8 中已经没有持久代。元空间的本质和永久代类似,都   JVM 规范中方法区的实现,不过元空间与永久代之间最大的区别在于:元空 间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受 本地内存限制,但可以通过以下参数来指定元空间的大小。

2.永久代

在自定义类加载器还不是很常见的时候,类大多是static的,很少被卸载或收集,因此被成为“永久的(Permanent)”。

同时,由于类class是JVM实现的一部分,并不是由应用创建的,所以又被认为是“非堆(Non-Heap)”内存。

在JDK8之前的HotSpot JVM,存放这些“永久的”区域叫做“永久代(permanent generation)”。

2.2.1. JVM 线程共享区应用分析

1. Heap (堆内存)
堆内存概要:
1) 虚拟机启动时创建,被所有线程共享 , 用于存放所有 java 对象实例 .
2) 可分为年轻代 (eden) 和老年代 (Tenured)
3) 是垃圾收集器(GC)管理的主要区域
4) 堆中没有内存分配时将会抛出 OutOfMemoryError
对象在内存中分配说明:
新创建的对象一般都分配在年轻代,当对象比较大时年轻代没有足够空间存储时还可直接分配到老年代。 有时候系统为了减少 GC 开销对于小对象且没有逃逸的对象还 可以直接在栈上分配。
堆内存大小配置参数说明:
1) -Xms 设置堆的最小空间大小。
2) -Xmx 设置堆的最大空间大小。
3) -XX:NewSize 设置新生代最小空间大小。
4) -XX:MaxNewSize 设置新生代最大空间大小。
5) -XX:NewRatio 新生代和老年代的比值,值为 4 则表示新生代 : 比老年代 1: 4
6) -XX:SurivorRatio 表示 Survivor eden 的比值,值为 8 表示两个 survivor:eden=2:8.
8) -Xss: 设置每个线程的堆栈大小。
2. Method Area (方法区)
方法区(1.8以后叫元数据区)概要:
1) 非堆内存,逻辑上的定义, 用于存储类的数据结构信息,常量、静态变量以及即时编译器编译后的代码等数据。
由于元 数据存储的信息不容易变动,因此它被安置在一块堆外内存。
2) 不同 jdk ,方法区的实现不同, JDK8(hotspot)  中的方法区对应的是 Metaspace,是一 块本地内存。
方法存储说明: 
方法区内存配置参数说明:
1) -XX:PermSize 设置永久代最小空间大小( JDK8 已弃用)。
2) -XX:MaxPermSize 设置永久代最大空间大小( JDK8 已弃用)。
3) -XX:MetaspaceSize 设置元数据区最小空间。 (JDK8)
4) -XX:MaxMetaspaceSize 设置元数据区最大空间。 (JDK8)

2.2.2. JVM 线程私有区应用分析

1. Program Counter Register (程序计数器)
1) 线程启动时创建,线程私有。
2) 用于记录当前正在执行的程序的字节码指令地址
3) Java 虚拟机规范唯一一个没有内存溢出的区域。
2. Stack Area (虚拟机栈区)
虚拟机栈概要:
1) 用于存储栈帧 (Stack Frame) 对象,保存方法的局部变量表操作数
行运行时常量池的引用一些额外的附加信息
2)每  一次方法调用都会创建一个新的栈帧,并压栈。当方法执行完毕之后,便会
将栈帧出栈。
3) 栈上对象的分配:对于小对象(一般几十个 bytes ),在没有逃逸的情况下,可以
直接分配在栈上(直接分配在栈上,可以自动回收,减轻 GC 压力);大对象
或者逃逸对象无法栈上分配
说明:方法在进行递归调用时容易出现栈内存溢出。
虚拟机栈参数说明:
1 -Xss128k : 设置每个线程的栈大小
JDK5.0 以后每个线程堆栈大小为 1M ,以前每个线程堆栈大小为 256K。可根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多 的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经 验值在 3000~5000 左右。
3. Native Stack Area (本地方法栈)

1) 为虚拟机使用到的 Native 方法提供服务。
2) 用于存储本地方法执行时的一些变量信息,操作数信息,结果信息。

 3.JVM 应用参数分析

3.1. 如何理解 JVM 中的内存溢出?

每个 Java 程序运行时都会使用一定量的内存 , JVM 内存不足以满足当前 java 程序运行时所需要的内存资源时就会出现内存溢出的现象。

代码演示:堆内存溢出

在如下代码中假如不断的向 list 集合中存储新的对象,list 集合底层也会不 断的进行扩容,当内存中没有足够连续内存 空间存储这些对象时就会出现堆内 存溢出。
public class TestOOM01 {public static void main(String[] args) {long t1=System.currentTimeMillis();try {List<byte[]> list=new ArrayList<>();for(int i=0;i<100;i++) {list.add(new byte[1024*1024]);}}finally {long t2=System.currentTimeMillis();
//System.out.println("oom:"+(t2-t1));}}
}
运行时可设置虚拟机参数
-Xmx50m -Xms10m -XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=e:/a.dump
说明:如上代码在运行了一段时间以后会出现堆内存溢出 (OutOfMemoryError), 可通过调整堆内存大小,延迟内存溢出的时间。

代码演示:元数据内存溢出(JDK8)

当在有限的元数据内存区不断的加载新的类时会导致元数据区空间不足从而出 现内存溢出现象,例如:
public class MetaSpaceTest {public static void main(String[] args) {int i = 0;try {for (i = 0; i < 100000; i++) {new CglibBean(new HashMap<>());}} catch (Exception e) {System.out.println(e.getMessage());} finally {System.out.println("total create count:" + i);}}public static class CglibBean {public CglibBean(Object object) {Enhancer enhancer = new Enhancer();enhancer.setUseCache(false);enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> obj);enhancer.setSuperclass(object.getClass());enhancer.create();}}
}

上述代码通过Cglib生成大量的HashMap代理,下面我们在运行这段代码的时候指定下列参数

-XX:MaxMetaspaceSize=100M -XX:+PrintGCDetails

当我们程序循环至3660次,也就是说我们大约在生成了约3660个代理类以后元数据区发生了内存溢出,下面将MaxMetaspaceSize改为50M执行,

 从上图可以看出当我们生成了1710个代理类以后元数据区发生了内存溢出,可见一个元数据区的大小决定了Java虚拟机可以装载的类的多少。

3.2. JVM 工具应用分析篇

3.2.1. 命令行工具篇

1. Jps [options] [hostid] (hostid ip 或域名地址)
jps 是用于查看有权访问的 hotspot 虚拟机的进程,当未指定 hostid 时,默认 查看本机 jvm 进程。
-q 不输出类名、 Jar 包 名和传入 main 方法的参数
-m 输出传入 main 方法的参数
-l 输出 main 类或 Jar 的全限名
-v 输出传入 JVM 的参数
 例如:
代码示例
执行:
1)Jps -l 输出应用程序主类完整 package 名称或 jar 完整名称 .
2)Jps -v 列出 jvm 参数
2. jmap -heap pid
用于打印指定 Java 进程的对象内存映射或堆内的细节。
代码案例
public class TestCommand {public static void main(String[] args) {while (true) {byte[] b1 = new byte[1024 * 1024];}}}
例如获取如上代码的进程 id 之后,执行 jmap -heap 24966 可检测堆的配置 信息,还可以借助 jmap -histo:live 1963 快速定位内存泄露。
其中:
1) MaxHeapFreeRatio:  最大空闲堆内存比例
最大空闲对内存比例, GC 后如果发现空闲堆内存大于整个预估堆内存的 N%(百分比 ) JVM 则会收缩堆内存,但不能小于 -Xms 指定的最小堆的限制。
2) MinHeapFreeRatio: 最小空闲堆内存比例
GC 后如果发现空闲堆内存小于整个预估堆内存的 N%( 百分比 ), JVM 会增大 堆内存,但不能超过 -Xmx 指定的最大堆内存限制。
3) MaxHeapSize: -Xmx, 堆内存大小的上限
4) InitialHeapSize: -Xms, 堆内存大小的初始值
5) NewSize: 新生代预估堆内存占用的默认值
6) MaxNewSize: 新生代占整个堆内存的最大值
7) OldSize: 老年代的默认大小 ,
8) NewRatio:
老年代对比新生代的空间大小 , 比如 2 代表老年代空间是新生代的两倍大小 .
9) SurvivorRatio:
Eden/Survivor 的值 . 例如 8 表示 Survivor:Eden=1:8, 因为 survivor   2 , 所以 新生代  Eden 的占比为 8/10 
10)MetaspaceSize:
分配给类元数据空间的初始大小 (Oracle 逻辑存储上的初始高水位,the initial high-water-mark ). 此值为估计值 . MetaspaceSize 设置得过大,会延长垃圾回收时间 . 垃圾回收过后 , 引起下一次垃圾回收的类元数据空间的 大小可能会变大
11)MaxMetaspaceSize:
是分配给类元数据空间的最大值 , 超过此值就会触发 Full GC. 此值仅受限系统内存的大小 , JVM 会动态地改变此值
12)CompressedClassSpaceSize:
类指针压缩空间大小 , 默认为 1G.
13)G1HeapRegionSize:
G1 区块的大小 , 取值为 1M 32M. 其取值是要根据最小 Heap 大小划分出 2048 个区块 .
说明 :jmap 在系统调优时通常会结合 jhat 来分析 jmap 生成的 dump 文件。
3. jstack 用于生成 java 虚拟机当前时刻的线程快照
生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。
示例代码:
class SyncTask02 implements Runnable {private List<Integer> from;private List<Integer> to;private Integer target;public SyncTask02(List<Integer> from, List<Integer> to, Integer target) {this.from = from;this.to = to;this.target = target;}@Overridepublic void run() {moveListItem(from, to, target);}private static void moveListItem(List<Integer> from,List<Integer> to, Integer item) {log("attempting lock for list", from);synchronized (from) {log("lock acquired for list", from);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}log("attempting lock for list ", to);synchronized (to) {log("lock acquired for list", to);if (from.remove(item)) {to.add(item);}log("moved item to list ", to);}}}private static void log(String msg, Object target) {System.out.println(Thread.currentThread().getName() +": " + msg + " " +System.identityHashCode(target));}
}public class TestDeadLock02 {public static void main(String[] args) {List<Integer> list1 = new ArrayList<>(Arrays.asList(2, 4, 6, 8,10));List<Integer> list2 = new ArrayList<>(Arrays.asList(1, 3, 7, 9,11));Thread thread1 = new Thread(new SyncTask02(list1, list2, 2));Thread thread2 = new Thread(new SyncTask02(list2, list1, 9));thread1.start();thread2.start();}
} 
例如 执行 jstack -l 22345 ,检测到死锁问题:
3.2.2. GUI 工具篇:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/311539.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript 高性能编程 —— 加载和运行

JavaScript 在浏览器中的性能,可认为是开发者所要面对的最重要的可用性问题。此问题因 JavaScript 的阻塞特征而复杂,也就是说,当 JavaScript 运行时其他的事情不能被浏览器处理。 事实上,大多数浏览 器使用单进程处理 UI 更新和 JavaScript 运行等多个任务,而同一时间只能…

ADB的基本语法及常用命令

学习网址 ADB命令的基本语法如下&#xff1a; adb [-d|-e|-s <serialNumber>] <command> 如果有多个设备/模拟器连接&#xff0c;则需要为命令指定目标设备。 参数及含义如下&#xff1a; 常用命令如下&#xff1a; 1. 启动ADB服务 adb start-server 2. 停止…

OpenHarmony实战开发-Worker子线程中解压文件。

介绍 本示例介绍在Worker 子线程使用ohos.zlib 提供的zlib.decompressfile接口对沙箱目录中的压缩文件进行解压操作&#xff0c;解压成功后将解压路径返回主线程&#xff0c;获取解压文件列表。 效果图预览 使用说明 1.点击解压按钮&#xff0c;解压test.zip文件&#xff0c…

Spring底层如何执行?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Spring底层如何执行refresh()prepareRefresh() 准备刷新的工作initPropertySources() obtainFreshBeanFactory()refreshBeanFactory()AbstractRefreshableApplicati…

【ensp】VLAN间通信的解决办法

目录 VLAN间通信简介 VLAN间通信的两种方式 借助三层设备路由器进行VLAN间的通信&#xff08;也就是单臂路由&#xff09; 在端口上创建子接口之后为什么需要开启arp广播&#xff0c;是因为他是子接口吗? 拓扑图 交换机配置 路由器配置 查看路由器配置 测试能否实现…

Element-Ui的Form表单:Label文本两端对齐,且必填项的*不影响布局

1. HTML 结构 首先&#xff0c;确保你的 HTML 或 Vue 模板中有一个 el-form 组件&#xff0c;类似下面这样&#xff1a; <div id"app"><el-form :model"form" label-width"100px"><el-form-item label"用户名">&l…

基于springboot的医护人员排班系统

随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了医护人员排班系统的开发全过程。通过分析医护人员排班系统管理的不足&#xff0c;创建了一个计算机管理医护人员排班系统的方案。文章介绍了医护人员排班系统的系统分…

更改ip地址的几种方式有哪些

在数字化时代&#xff0c;IP地址作为网络设备的标识&#xff0c;对于我们在网络世界中的活动至关重要。然而&#xff0c;出于多种原因&#xff0c;如保护隐私、访问特定网站或进行网络测试&#xff0c;我们可能需要更改IP地址。虎观代理将详细介绍IP地址的更改方法与步骤&#…

【JavaSE】你真的了解内部类吗?

前言 本篇会详细讲解内部类的四种形式&#xff0c;让你掌握内部类~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 内部类介绍 实例内部类 定义 调用 静态内部类 定义 调用 匿名内部类 定义和调用1 调用方法2 …

预分频器×重装载值)/LSI频率 为什么等于总时间

1. 第一种算法理解&#xff1a;分频系数 64 &#xff0c;外部低速时钟40khz&#xff0c; 则一次计数周期1.6ms &#xff0c;计数625个数&#xff0c;则有625个周期 &#xff0c;1.6ms*625 等于1s 如果分频系数是64&#xff0c;外部低速时钟&#xff08;LSI&#xff09;频率是…

gitee和idea集成

1 集成插件 2 配置账号密码 3 直接将项目传到仓库 4直接从gitee下载项目

【CAN】采样点介绍及测试方法

文章目录 1 什么是采样点2 为什么需要采样点3 采样点的计算公式4 VH6501测试原理和方法4.1 VH6501测试采样点原理4.2 VH6501测试方法 >>返回总目录<< 1 什么是采样点 采样点是节点判断信号逻辑电平的位置&#xff0c;是CAN控制器读取总线电平&#xff0c;并解释各…

前端console用法分享

console对于前端人员来讲肯定都不陌生&#xff0c;相信大部分开发者都会使用console来进行调试&#xff0c;但它能做的绝不仅限于调试。 最常见的控制台方法 作为开发者&#xff0c;最常用的 console 方法如下&#xff1a; 控制台打印结果&#xff1a; 今天我分享的是一些 co…

网络爬虫:定义、应用及法律道德考量

网络爬虫技术在当今数据驱动的世界中发挥着重要作用。本文将从网络爬虫的定义和主要功能&#xff0c;其在业界的应用实例&#xff0c;以及涉及的法律和道德问题三个方面进行深入探讨。 1. 爬虫的定义和主要功能 网络爬虫&#xff0c;也称为网页爬虫或蜘蛛&#xff0c;是一种…

【C++对于C语言的扩充】函数重载、引用以及内联函数

文章目录 &#x1f680;前言&#x1f680;函数重载注意&#xff1a;✈️为什么C可以实现函数重载&#xff0c;而C语言却不行呢&#xff1f; &#x1f680;引用✈️引用的特性✈️C中为什么要引入引用✈️引用与指针的区别 &#x1f680;内联函数✈️内联函数特性 &#x1f680;…

【云计算】云数据中心网络(四):IPv6 网关

云数据中心网络&#xff08;四&#xff09;&#xff1a;IPv6 网关 1.什么是 IPv6 网关2.IPv6 网关设计思路3.IPv6 网关的主要应用场景3.1 IPv6 私网通信3.2 IPv6 互联网通信3.3 IPv6 互联网通信&#xff08;仅主动访问&#xff09; 1.什么是 IPv6 网关 2017 年&#xff0c;中国…

【十一】MyBatis Plus 原理分析

MyBatis Plus 原理分析 摘要 Java EE开发中必不可少ORM框架&#xff0c;目前行业里最流行的orm框架非Mybatis莫属了&#xff0c;而Mybatis框架本身没有提供api实现&#xff0c;所以市面上推出了Mybatis plus系列框架&#xff0c;plus版是mybatis增强工具&#xff0c;用于简化My…

JavaWeb前端/后端开发规范——接口文档概述及YApi平台的使用

前言&#xff1a; 整理下笔记&#xff0c;打好基础&#xff0c;daydayup!!! 接口文档 什么是接口文档&#xff1f; 目前主流的开发模式为前后端分离式开发&#xff0c;为了方便前后端的对接&#xff0c;就需要使用接口文件进行统一规范。 接口文档记载什么信息&#xff1f; 1&…

中国科学院大学学位论文LaTeX模版

Word排版太麻烦了&#xff0c;公式也不好敲&#xff0c;推荐用LaTeX模版&#xff0c;全自动 官方模版下载位置&#xff1a;国科大sep系统 → \rightarrow → 培养指导 → \rightarrow → 论文 → \rightarrow → 论文格式检测 → \rightarrow → 撰写模板下载百度云&#…