JVM(一)——内存结构

news/2024/4/29 14:38:43/文章来源:https://blog.csdn.net/m0_72406127/article/details/136986014

一. 前言

1、什么是 JVM?

1)定义:
Java Virtual Machine - java 程序的运行环境(java 二进制字节码的运行环境)
2)好处:

  • 一次编写,到处运行
  • 自动内存管理,垃圾回收功能
  • 数组下标越界检查
  • 多态

3)比较:
jvm jre jdk的关系如下图
在这里插入图片描述

2、学习 JVM 有什么用 ?

  • 面试
  • 理解底层的实现原理
  • 中高级程序员的必备技能

3、常见的JVM

在这里插入图片描述

4、学习路线

在这里插入图片描述

二、内存结构

1、程序计数器

1)定义
Program Counter Register 程序计数器(寄存器)
作用,是记住下一条jvm指令的执行地址
特点

  • 是线程私有的
  • 不会存在内存溢出

2)作用

0: getstatic #20 // PrintStream out = System.out; 
3: astore_1 // -- 
4: aload_1 // out.println(1); 
5: iconst_1 // -- 
6: invokevirtual #26 // -- 
9: aload_1 // out.println(2); 
10: iconst_2 // -- 
11: invokevirtual #26 // -- 
14: aload_1 // out.println(3); 
15: iconst_3 // -- 
16: invokevirtual #26 // -- 
19: aload_1 // out.println(4); 
20: iconst_4 // -- 
21: invokevirtual #26 // -- 
24: aload_1 // out.println(5); 
25: iconst_5 // -- 
26: invokevirtual #26 // -- 
29: return
  • 解释器会解释指令为机器码交给 cpu 执行,程序计数器会记录下一条指令的地址行号,这样下一次解释器会从程序计数器拿到指令然后进行解释执行。
  • 多线程的环境下,如果两个线程发生了上下文切换,那么程序计数器会记录线程下一行指令的地址行号,以便于接着往下执行。

2、虚拟机栈

1)定义
Java Virtual Machine Stacks (Java 虚拟机栈)

  • 每个线程运行时所需要的内存,称为虚拟机栈
  • 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

问题辨析:

  1. 垃圾回收是否涉及栈内存?
    不涉及栈内存,栈内存是在方法调用时产生的,栈帧在每次弹出栈后,会被自动回收掉。
  2. 栈内存分配越大越好吗?
    不是。因为物理内存是一定的,栈内存越大,可以支持更多的递归调用,但是可执行的线程数就会越少。
  3. 方法内的局部变量是否线程安全
    • 如果方法内部的变量没有逃离方法的作用访问,它是线程安全的-
    • 如果是局部变量引用了对象,并逃离了方法的访问,那就要考虑线程安全问题。

2)栈内存溢出

报错: java.lang.StackOverFlowError

  • 栈帧过多会导致栈内存溢出。常发生在递归调用过多,或循环引用问题
  • 栈帧过大会导致栈内存溢出
    -Xss指令可以为虚拟机栈分配内存大小。

3)线程运行诊断
案例:cpu 占用过多

  • 用top定位哪个进程对cpu的占用过高
  • ps H -eo pid,tid,%cpu | grep 进程id (用ps命令进一步定位是哪个线程引起的cpu占用过高)
  • jstack 进程id
    • 可以根据线程id 找到有问题的线程,进一步定位到问题代码的源码行号

3、本地方法栈

java 语言调用其他语言的方法或接口,实现更底层的应用和操作,本地方法栈就是用来存储的。例如 java 中的 native 关键字所引用的就是 c 或 c++ 的方法。

4、堆

1)定义
Heap 堆

  • 对于Java应用程序来说,Java堆(Java Heap)是虚拟机所管理的内存中最大的一块。Java堆是被所
    有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java
    世界里“几乎”所有的对象实例都在这里分配内存。

特点

  • 它是线程共享的堆中对象都需要考虑线程安全的问题
  • 有垃圾回收机制

2)堆内存溢出

报错:java.lang.OutOfMemoryError: Java heap space

-Xmx 指令可以指定堆内存大小。

3)堆内存诊断

  1. jps 工具
    查看当前系统中有哪些 java 进程
  2. jmap 工具
    查看堆内存占用情况 jmap - heap 进程id
  3. jconsole 工具
    图形界面的,多功能的监测工具,可以连续监测
  4. jvisualvm 工具

5、方法区

1)定义
方法区和堆一样,是各个线程共享的内存区域,存储了每个类的结构,例如成员变量、静态变量、方法数据、成员方法、构造器和运行时常量池。
虽然方法区逻辑上是堆的一部分,但是简单的实现可以不同,方法区只是一个规范,例如jdk8之前hotspot虚拟机的"永久代"就是方法区的实现方式之一。jdk8后,使用hotspot虚拟机使用"元空间"的方式实现方法区,也就是在本地内存来实现元空间。

2)组成
在这里插入图片描述
3)方法区内存溢出

jdk1.8之前 报错:java.lang.OutOfMemoryError: PermGen space
jdk1.8之后 报错:java.lang.OutOfMemoryError: Meta space

使用 -XX:MaxPermSize=8m 指定永久代内存大小
使用 -XX:MaxMetaspaceSize=8m 指定元空间大小
场景:

  • spring
  • mybatis

    cglib

4)运行时常量池
运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字
段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生
成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

*.class 文件目录下使用javap -v ./HelloWorld.class查看二进制字节码(类基本信息,常量池,类方法定义,包含了虚拟机指令)
在这里插入图片描述
在这里插入图片描述

  • 常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量
    等信息
  • 运行时常量池,常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量
    池,并把里面的符号地址变为真实地址

5)StringTable

StringTable 底层是 HashTable ,存储的字符串是唯一的,不能扩容。

常量池中的信息,都会被加载到运行时常量池中,这时 a b ab 都是常量池中的符号,还没有变为 java 字符串对象

public static void main(String[] args) {String s1 = "a";	// 默认懒加载String s2 = "b";String s3 = "ab";		// 在 StringTable 字符串常量池中创建String s4 = s1 + s2;	// new StringBuilder().append("a").append("b").toString(); => new String("ab");	在堆中创建的对象String s5 = "a" + "b";	// javac 在编译期间的优化,结果已经在编译期间确定为 ab,即 s5 == s3 -> true
}

在这里插入图片描述

6)StringTable 的特性

  • 常量池中的字符串仅是符号,第一次用到时才变为对象
  • 利用串池的机制,来避免重复创建字符串对象
  • 字符串变量拼接的原理是 StringBuilder (1.8)
  • 字符串常量拼接的原理是编译期优化
  • 可以使用 intern 方法,主动将串池中还没有的字符串对象放入串池
    • 1.8 将这个字符串对象尝试放入串池,如果有则直接返回串池中的对象,如果没有则放入串池, 会把串池中的对象返回
    • 1.6 将这个字符串对象尝试放入串池,如果有则直接返回串池中的对象,如果没有会把此对象复制一份,放入串池, 会把串池中的对象返回

例1:

// 在 jdk1.8中
public class Main{public static void main(String[] args) {// 串池StringTable["a", "b"]// 堆 new String("a"), new String("b"), new StringBuilder() * 3, new String("ab")String s = new String("a") + new String("b");	//一共创建了 6 个对象// TODO: 字符串对象s调用intern()方法, 由于串池中没有"ab",将 s 放入串池中,直接返回串池中的对象String s2 = s.intern();		String x = "ab";	// 取出串池中的 "ab"System.out.println( s2 == x);	// trueSystem.out.println( s == x );	// true}
}

例2:

// 在 jdk1.6中
public class Main{public static void main(String[] args) {// 串池StringTable["a", "b"]// 堆 new String("a"), new String("b"), new StringBuilder() * 3, new String("ab")String s = new String("a") + new String("b");	//一共创建了 6 个对象// TODO: 字符串对象s调用intern()方法, 由于串池中没有"ab", 字符串对象s会被复制一份放到串池中,返回串池中的对象String s2 = s.intern();		String x = "ab";		// 取出串池中的 "ab"System.out.println( s2 == x);	// trueSystem.out.println( s == x );	// false}
}

7)StringTable的位置

jdk1.6 StringTable 位置是在永久代中,1.8 StringTable 位置是在堆中。

8)StringTable垃圾回收
添加虚拟机参数:-Xmx10m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc

public class Demo1_7 {public static void main(String[] args) throws InterruptedException {int i = 0;try {for (int j = 0; j < 10000; j++) { // j=100, j=10000String.valueOf(j).intern();i++;}} catch (Throwable e) {e.printStackTrace();} finally {System.out.println(i);}}
}
[GC (Allocation Failure) [PSYoungGen: 2048K->496K(2560K)] 2048K->720K(9728K), 0.0015984 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
10000 	# 10000个字符被GC回收了一部分
...
StringTable statistics:
Number of buckets       :     60013 =    480104 bytes, avg   8.000
Number of entries       :      5671 =    136104 bytes, avg  24.000
Number of literals      :      5671 =    346048 bytes, avg  61.021	# 字符串常量池中的字符串
Total footprint         :           =    962256 bytes

9)StringTable性能调优

如果需要添加的字符串常量的数量很多,可以适当增加HashTable桶的个数,来减少字符串放入串池所需要的时间。

-XX:StringTableSize=桶个数(最少设置为 1009 以上)
  • 考虑将字符串对象是否入池
    • 可以通过 intern 方法减少重复入池

6、直接内存

1)定义

  • 常见于 NIO 操作时,用于数据缓冲区
  • 分配回收成本较高,但读写性能高
  • 不受 JVM 内存回收管理

2)分配和回收原理

  • 使用了 Unsafe 对象完成直接内存的分配回收,并且回收需要主动调用 freeMemory 方法
  • ByteBuffer 的实现类内部,使用了 Cleaner (虚引用)来监测 ByteBuffer 对象,一旦
    ByteBuffer 对象被垃圾回收,那么就会由 ReferenceHandler 线程通过 Cleaner 的 clean 方法调
    用 freeMemory 来释放直接内存。

在进行JVM调优时,尝试用-XX:+DisableExplicitGC指令,可以防止我们自己手动的进行垃圾回收 (System.gc())。
但是在直接内存中,JVM无法自动对直接内存进行垃圾回收,我们可以通过 Unsafe 中的 freeMemory 方法手动释放内存

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

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

相关文章

React Native 应用打包上架

引言 在将React Native应用上架至App Store时&#xff0c;除了通常的上架流程外&#xff0c;还需考虑一些额外的优化策略。本文将介绍如何通过配置App Transport Security、Release Scheme和启动屏优化技巧来提升React Native应用的上架质量和用户体验。 配置 App Transport…

基于振弦采集仪的土体变形监测与分析

基于振弦采集仪的土体变形监测与分析 工程监测振弦采集仪是一种专用于工程监测中的振弦测量的仪器。它能够实时采集及记录结构物的振动信号&#xff0c;以评估结构物的健康状况、安全性能等。它通常由振弦传感器、数据采集模块和数据处理软件组成。振弦传感器负责测量结构物的…

uniApp使用XR-Frame创建3D场景(5)材质贴图的运用

上一篇讲解了如何在uniApp中创建xr-frame子组件并创建简单的3D场景。 这篇我们讲解在xr-frame中如何给几何体赋予贴图材质。 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"><xr-node><xr-assets><xr-asse…

联想 lenovoTab 拯救者平板 Y700 二代_TB320FC原厂ZUI_15.0.677 firmware 线刷包9008固件ROM root方法

联想 lenovoTab 拯救者平板 Y700 二代_TB320FC原厂ZUI_15.0.677 firmware 线刷包9008固件ROM root方法 ro.vendor.config.lgsi.market_name拯救者平板 Y700 ro.vendor.config.lgsi.en.market_nameLegion Tab Y700 #ro.vendor.config.lgsi.short_market_name联想平板 ZUI T # B…

2024多云管理平台CMP排名看这里!

随着云计算技术的迅猛发展&#xff0c;多云管理平台CMP应运而生。多云管理平台CMP仅能够简化对多个云环境的统一管理&#xff0c;还能提高资源利用效率和降低成本。因此了解多云管理平台CMP品牌是必要的。2024多云管理平台CMP排名看这里&#xff01;仅供参考哈&#xff01; 20…

Java八股文(JVM)

Java八股文のJVM JVM JVM 什么是Java虚拟机&#xff08;JVM&#xff09;&#xff1f; Java虚拟机是一个运行Java字节码的虚拟机。 它负责将Java程序翻译成机器代码并执行。 JVM的主要组成部分是什么&#xff1f; JVM包括以下组件&#xff1a; ● 类加载器&#xff08;ClassLoa…

【SpringBoot从入门到精通】03_SpringBoot自动配置原理

三、SpringBoot自动配置原理 我们通过编写SpringBoot HelloWorld程序&#xff0c;体会到了其强大与便捷&#xff0c;它的这些功能都是基于SpringBoot的依赖管理与自动配置。 3.1 核心特性 依赖管理 父项目做依赖管理 <!-- 当前项目的父项目&#xff1a;依赖管理 --> &…

MySQL进阶-----索引的语法与SQL性能分析

目录 前言 一、索引语法 1.SQL语法 2.案例演示 二、SQL性能分析 三、慢查询日志 1.开启日志 2.测试样例 四、profile详情 1.开启profile 2.profile测试SQL语句 五、explain详情 1.语法结构 2.执行顺序示例&#xff08;id&#xff09; 3.执行性能示例(type) 前言 本…

每日一题--最长连续序列

洛阳春-岑参 人到洛阳花似锦&#xff0c;偏我来时不逢春。 谁道三冬无春色&#xff0c;冰山高处万里银 目录 题目描述 思路分析 方法及其时间复杂度 法一 暴力枚举&#xff1a; 法二 哈希表遍历&#xff1a; 法三 并查集&#xff1a; 个人总结 题目描述 128. 最长连续序…

JVM快速入门(2)HotSpot和堆、新生区、永久区、堆内存调优、JProfiler工具分析OOM原因、GC(垃圾回收)、JVM经典面试笔试题整理

5.6 HotSpot和堆 5.6.1 Hotspot 三种JVM&#xff1a; Sun公司&#xff0c;HotspotBEA&#xff0c;JRockitIBM&#xff0c;J9 VM&#xff0c;号称是世界上最快的Java虚拟机 我们一般学习的是&#xff1a;HotSpot 5.6.2 堆 Heap&#xff0c;一个JVM只有一个堆内存&#xff0c…

【I.MX6ULL移植】Ubuntu-base根文件系统移植

1.下载Ubuntu16.04根文件系统 http://cdimage.ubuntu.com/ 1 2 3 4 5 2.解压ubuntu base 根文件系统 为了存放 ubuntu base 根文件系统&#xff0c;先在 PC 的 Ubuntu 系统中的 nfs 目录下创建一个名为 ubuntu_rootfs 的目录&#xff0c;命令如下&#xff1a; 【注意&…

【IP 组播】PIM-SM

目录 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置IGP 3.配置PIM-SM 4.用户端DR与组播源端DR 5.从RPT切换到SPT 6.配置PIM-Silent接口 原理概述 PIM-SM 是一种基于Group-Shared Tree 的组播路由协议&#xff0c;与 PIM-DM 不同&#xff0c;它适合于组播组成…

【word技巧】word复制整页格式不变,如何做到?

Word文档内容中的某页需要复制粘贴到其他word文档&#xff0c;如何做才能保持整页格式不变&#xff1f;今天分享几个方法&#xff0c;帮助大家解决word复制整页格式不变。 方法一&#xff1a; 最简单的方法就是&#xff0c;找到需要复制的页面&#xff0c;从第一行使用光标选…

鸿蒙TypeScript开发入门学习第3天:【TS基础类型】

1、TypeScript 基础类型 TypeScript 包含的数据类型如下表: 注意&#xff1a; TypeScript 和 JavaScript 没有整数类型。 2、Any 类型 任意值是 TypeScript 针对编程时类型不明确的变量使用的一种数据类型&#xff0c;它常用于以下三种情况。 1、变量的值会动态改变时&…

连续信号离散信号的功率谱密度--用MATLAB求功率谱密度

连续信号&离散信号的功率谱密度--用MATLAB求功率谱密度 目录 前言 一、能量及功率定义 1、连续信号 2、离散信号 二、功率谱密度计算公式 三、MATLAB仿真 1、源代码 2、仿真结果分析 总结 前言 一直对数字信号处理中的功率谱密度计算有点好奇&#xff0c;虽然MATLAB有提供现…

提升K8S故障排除效率:详解Pod内抓包的高效策略!

在Kubernetes环境中&#xff0c;故障排除是管理者日常工作中不可或缺的一部分。随着容器化应用的广泛采用&#xff0c;需要一种高效的方法来诊断和解决Pod内部的问题。本文将重点介绍如何利用抓包技术提升Kubernetes环境中Pod内部故障排除的效率。 为什么需要Pod内抓包 在Kube…

零售商品计划新篇章:智能管理系统的挑战与机遇

在零售企业管理中&#xff0c;商品计划管理在零售企业运营中占据核心地位。面对日益激烈的市场竞争和消费者需求的多样化&#xff0c;零售企业在商品计划管理方面面临着诸多挑战和需求。以下针对这些挑战和需求的分析&#xff0c;以及对一套智能商品计划管理系统应具备的功能和…

高效运维|AIRIOT智慧电力运维解决方案

可再生能源的引入带来了能源生产的去中心化和分散化趋势&#xff0c;同时也带来了能源输出的波动性和不确定性。电力运维因此需要更加灵活、智能的解决方案&#xff0c;以适应可再生能源的集成&#xff0c;确保电力系统的稳定运行&#xff0c;传统的电力运维管理方式往往存在如…

Vite 为什么比 Webpack 快?

目录 1. Webpack 的构建原理 2. Script 的模块化&#xff08;主流浏览器对 ES Modules 的支持&#xff09; 3. Webpack vs Vite 开发模式的差异 对 ES Modules 的支持 底层语言的差异 热更新的处理 1. Webpack 的构建原理 前端之所以需要类似于 Webpack 这样的构建工具&…

【教学类-40-09】A4骰子纸模制作9.0(3.47CM嵌套骰子 一条8格便于对折,表格相连 一页3个 油墨打印A4铅画纸)

作品展示 背景需求&#xff1a; 骰子调整到第8版&#xff0c;把骰子图案作成一长条&#xff0c;便于切割裁剪。 【教学类-40-08】A4骰子纸模制作8.0&#xff08;2.97CM嵌套骰子表格相连 一页7个 油墨打印A4铅画纸&#xff09;-CSDN博客文章浏览阅读929次&#xff0c;点赞20次…