最简单的JVM内存结构图

article/2025/10/10 18:16:45

目录

 

JVM内存结构图

方法区

程序计数器

本地方法栈

直接内存

内存分配性能优化-逃逸分析

总结


JVM内存结构图


image.png

大家好,好几天没有更新了,今天的内容有点多,我们详细介绍下JVM内部结构图,还是和之前一样,案例先行,方便大家理解记忆。

/*** @author :jiaolian* @date :Created in 2021-03-10 21:28* @description:helloworld测试jvm内存区域* @modified By:* 公众号:叫练*/
public class HelloWorldTest {public static void main(String[] args) {//新建HelloWorldTest对象;HelloWorldTest helloWorldTest = new HelloWorldTest();//新建2个线程调用sayHellofor (int i=0; i<2; i++) {new Thread(()->helloWorldTest.sayHello("world")).start();}}/*** 对某人说hello* @param who*/public void sayHello(String who) {System.out.println(Thread.currentThread().getName()+"hello!"+who);}
} 

如上代码:在主线程中for循环新建2个线程调用sayHello,最后两个线程分别对世界问好!这段代码比较好理解,就不贴输出结果了。我们编写并运行了这段代码,我们主要看看这段代码在JVM中是怎么运作的。

首先,我们编写一个HelloWorldTest.Java文件,经过javac编译会转化成字节码HelloWorldTest.class,为什么要转化成字节码呢?因为Java虚拟机能识别!最后由类加载子系统ClassLoader将字节码装载到内存。每块内存各有自己的作用,最后由执行引擎来执行字节码。下面我们重点介绍下各块内存发挥的作用!

image.png

 

方法区


方法区主要装一些静态信息,比如:类元数据,常量池,方法信息,类变量等。如上代码HelloWorldTest.class是类元数据,sayHello,main都是方法信息等都是放在方法区存储的。方法区中还需要注意两点:

  1. 如果方法区太大,超过设置,会报OutOfMemoryError:PermGen space错误。gclib工具可以动态生成类测试该错误。
  2. 在JDK1.7以前,方法区叫永久代,而1.8之后叫元空间。原因是JDK1.8为了释放管理压力,把运行时常量池交给堆去管理。

 


堆中主要存放实例对象。你可以这么理解,只要看到用关键字new的对象,数据都放在堆中。如上代码HelloWorldTest helloWorldTest = new HelloWorldTest();helloWorldTest是HelloWorldTest对象的引用,指向new出来的HelloWorldTest对象实例,helloWorldTest引用是放在栈中的,也叫局部变量方法内申明的对象类型或普通类型),我们简单画图来表示下堆,栈,方法区关系。当JVM执行了HelloWorldTest helloWorldTest = new HelloWorldTest();这句话,JVM内存结构看起来是这样的。如果指向对象引用消失,对象会被GC回收。

image.png

在堆内存中,内存需要划分成两块区域,新生代老年代。如下图所示。

  1. 新生代:在堆内存中,新生代又分为三块,eden(伊甸园创建新生命,对应new对象),from,to,这三块内存区域都属于新生代,默认比例是8:1:1,每次new对象都会先存储到eden中,如果eden区域内存满了,会触发monitor gc回收该区域,还未回收的对象会放入from或者to,from,to内存其中一块是空的,方便对象在内存中整理标记,每GC一次,from,to两块空间对象每移动一次,还未回收的对象年纪也会增加1,到达一定年纪(默认是15岁),就会进入老年代了。
  2. 老年代:当老年代满了,会触发Full GC回收,如果系统太大,Full GC都回收不了,程序会出现类似java.lang.OutOfMemoryError: Java heap space,我们可以通过配置JVM参数:如-Xmx32m 设置最大堆内存为32M。

对堆分块原因是方便JVM自动处理垃圾回收堆内存是GC回收的主要区域

image.png

 

 


栈内存空间相对于堆空间比较小,也属于线程私有,栈中主要是一堆栈帧,是先进后出的,理解起来栈帧对应就是一个方法,方法中包含局部变量,方法参数,还有方法出口,访问常量指针,和异常信息表,其中异常信息表和常量指针信息我们在方法体中可能看不出来,但通过工具Jclasslib工具类在反编译class文件可以体现出来,异常信息表可以处理当程序执行报错,会跳转到具体哪行代码执行,JVM中就是通过异常表反馈的。我们还是结合例子和图来详细分析下。当程序运行时,JVM中栈可能如下图呈现状态。

image.png    

一个线程可能对应多个栈帧,栈帧都是从上往下压入,先进后出,如下图所示,在方法A中调用方法B,在方法B中调用C,在方法C中调用方法D,主线程对应栈帧的压栈情况,出栈顺序是D->C->B->A,最终程序结束。另外还需注意:操作数栈的意思是存储局部变量计算的中间结果,比如在方法A中定义int x = 1;在JVM中会将局部变量入操作数栈用来之后的计算。栈也是有空间大小的,如果栈太大,超过栈深度,会类似报错,java.lang.OutOfMemoryError: Java stack space,最常见的例子就是递归了。你会写demo测试递归例子吗?

 

image.png

 

程序计数器


程序计数器也是线程独享的,多线程执行程序依赖于CPU分配时间片执行,画个简单的图,看看多线程怎么利用CPU时间片的。如下图,线程0和线程1分配cpu时间片交替执行程序,假设此时线程0先获取到了时间片,时间片用完后CPU会将时间片再分配给线程1,线程1执行完毕后,此时,时间片又回到线程0来执行,那么问题来了,线程0上次执行到哪儿了呢?具体是代码的多少行了呢,该行代码有没有执行完毕?此时程序计数器就发挥作用了,程序计数器保存了线程的执行现场,方便下次恢复运行。这也是为什么程序计数器是线程独享的原因。

image.png

 

 

本地方法栈


本地方法栈就不过多介绍了,和栈结构一样,是一块独立的区域,只是对应的是native方法。

 

直接内存


直接内存独立于JVM内存之外的内存,可以直接和NIO接口交互,NIO接口会频繁操作内存,如果放在JVM管理,无疑会增加JVM开销,所以单独将这块提出来,而且直接内存操作数据相比较JVM更快,显而易见提升了程序性能。

 

 

内存分配性能优化-逃逸分析


我们之前说过,只要是看到关键字new,对象分配肯定在堆上,下面我们来看一个案例。

/*** @author :jiaolian* @date :Created in 2021-03-10 16:10* @description:逃逸分析测试* @modified By:* 公众号:叫练*/
public class EscapeTest {//private static Object object;public static void alloc() {//一个对象相当于16k大小,非逃逸对象//object = new Object();Object object = new Object();}public static void main(String[] args) throws InterruptedException {//亿次内存long begin=System.currentTimeMillis();for (int i=0; i<10000000; i++) {alloc();}long end=System.currentTimeMillis();System.out.println("time:"+(end-begin));}
}

如上代码,我们在主函数里面通过for循环1亿次来new Object,一个object为16k,大致估算下有GB数据了,此时我们手动配置JVM参数,-XX:+PrintGC -Xmx10M -XX:+DoEscapeAnalysis;设置打印GC信息,默认最大的堆内存是10M。

  1. -XX:+PrintGC。表示控制台打印GC信息。
  2. -Xmx10M。设置最大的堆内存为10M。
  3. -XX:+DoEscapeAnalysis。 开启逃逸分析(默认开启)。

执行程序,打印结果如下图所示。一共进行了3次GC,你可能有疑问10M堆内存需要容纳GB数据冲击,怎么也需要N次GC,为什么只有3次GC?如果设置-XX:-DoEscapeAnalysis关闭逃逸分析,GC可能会出现上千次。运行时间也从3毫秒增至1000毫秒以上。说明了非逃逸对象没有新建的堆上,而是建在栈上了。这样做的好处:从程序GC执行次数和执行时间上来看,程序运行效率提高了。

image.png

  • 原因分析:

观察我们上述案例代码中alloc()方法,方法中Object object = new Object();object是一个局部变量,每次新建后到下一次循环再新建,上一次新建的对象就会出栈,object引用指向的对象就会失效,失效的对象就会被GC回收了。开启逃逸分析后,new Object()创建的对象就不在堆上分配空间了,而放到了栈上。这就是JVM通过逃逸分析对内存的优化。思考下,如果将private static Object object;注释放开,object还会是非逃逸对象吗?

注意:逃逸对象不能在栈上分配空间!

相信到这里你已经对逃逸分析应该有一个比较清晰的认识了。

 

总结


好了,写的有点累了,写的不全同时还有许多需要修正的地方,希望亲们加以指正和点评,喜欢的请点赞加关注哦。点关注,不迷路,我是【叫练公众号,微信号【jiaolian123abc】边叫边练。

image.png


http://chatgpt.dhexx.cn/article/aGV2b58Z.shtml

相关文章

JVM进阶(十一):JAVA G1收集器

文章目录 一、前言 一、前言 G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中&#xff0c;成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器一样&#xff0c;G1也是关注最小时延的垃圾回收器&#xff0c;也同…

JVM监控之图形化工具

一、工具概述 使用命令行工具存在以下的局限性&#xff1a; 无法获取方法级别的分析数据&#xff0c;如方法之间的调用关系、各方法的调用次数和调用时间等要去用户登陆到java应用所在的宿主机上分析数据通过终端输出&#xff0c;结构不够直观 随着java应用的官方使用&#…

Java 知识结构图

简介 《 值得去的地方&#xff0c;没有捷径&#xff1b;难走的路才更值得开始 》 为什么要说这个【知识结构图】呢&#xff0c;其实是针对于刚开始学习&#xff0c;工作或工作一段时间的人&#xff0c;每天忙&#xff0c;杂七杂八&#xff0c;自己身心巨累&#xff0c;又想要偷…

Java程序员必备基础结构图

前言 最近看了深入理解Java虚拟机第三版&#xff0c;整理了一些基础结构图&#xff0c;算是比较全的了&#xff0c;做一下笔记&#xff0c;大家一起学习。 1.Java虚拟机运行时数据区图 JVM内存结构是Java程序员必须掌握的基础。 程序计数器 程序计数器&#xff0c;可以看作…

JVM 结构图

一&#xff1a;Java技术体系模块图 二&#xff1a;JVM内存区域模型 1.方法区 也称"永久代” 、“非堆”&#xff0c; 它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB&#xff0c;最大值为64MB&#xff0c;可以通过-XX:Per…

JVM结构、GC工作机制详解

题外话&#xff1a;最近在应聘阿里2015暑期实习&#xff0c;感触颇多。机会总是留给有准备的人的&#xff0c;所以平常一定要注意知识的巩固和积累。知识的深度也要有一定的理解&#xff0c;不比别人知道的多&#xff0c;公司干嘛选你&#xff1f;关于JVM和GC&#xff0c;我相信…

详解 JVM Garbage First(G1) 垃圾收集器

前言 Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。如果使用Java 8/9,那么有很大可能希望对G1收集器进行评估。本文详细首先对JVM其他的垃圾收集器进行总结,并与G1进行了简单的对比;然后通过G1的内存模型、G1…

【JVM】JVM内存结构之——G1收集器

目录 1. 什么是G12. G1收集器发展历程3. G1收集器分区划分3.1 为什么G1收集器需要设计巨型对象3.2 G1收集器参数设置 3.3 G1收集器回收的细节3.4 G1收集器Rset问题&#xff08;记忆集&#xff09;3.5 G1两种回收策略4. G1收集器优缺点 5. G1收集器核心配置参数 1. 什么是G1 G1…

Visual Studio C# WinForm开发入门(5):TabControl 控件使用

TabContrl选项卡控件可创建标签化窗口&#xff0c;在实际 编程中经常用到&#xff0c;该控件的作用是将相关的组件组合到一系列选项卡页面上。 比如下面的例子&#xff0c;在tabPage1页面和tabPage2页面各放了2个checkBox控件&#xff0c;通过点击不同page即可切换&#xff1a;…

WPF自定义TabControl样式

WPF自定义TabControl样式 原文: WPF自定义TabControl样式 WPF自定义TabControl&#xff0c;TabControl美化 XAML代码&#xff1a; <TabControl x:Class"SunCreate.Common.Controls.TabControlEx"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/present…

C# WinForm TabControl美化

窗口Load加下面代码&#xff0c;ItemSize根据自己显示文本长度调整 #region tabMainItem属性设置this.tabModuleMainItem.DrawMode TabDrawMode.OwnerDrawFixed;this.tabModuleMainItem.Alignment TabAlignment.Top;this.tabModuleMainItem.SizeMode TabSizeMode.Fixed;this…

浅谈C#tabcontrol应用

作为Winfrom开发者来说&#xff0c;我们很多时候会用到tabcontrol来实现和网页标签页相关的效果。同时微软自带的控件样式不符合我们的需求&#xff0c;我们该如何去实现更加美观且可以自定义的组合控件呢&#xff1f;带着这个问题进入我们今天的主题&#xff0c;组合控件tabco…

C# WPF TabControl控件用法详解

概述 TabControl我之前有讲过一节&#xff0c;内容详见&#xff1a; C# WPF TabControl用法指南(精品)&#xff0c;上节主要讲解了tabcontrol控件的左右翻页&#xff0c;以及页面筛选&#xff0c;以及数据绑定等内容&#xff0c;这节内容继续接续上节内容进行扩展讲解&#xff…

WPF 自定义控件TabControl

WPF 自定义控件TabControl 新TabControl效果&#xff1a; 新添加一个自定义控件ZTabControl&#xff1a; public class ZTabControl : TabControl{#region Private属性#endregion#region 依赖属性定义public static readonly DependencyProperty TypeProperty;#endregion#r…

Winform TabControl标签美化

前期工作&#xff1a; 加载资源文件&#xff0c;双击“Resources.resx" 类型选择Images 【添加资源】——【添加现有文件】 选择需要添加的图片文件&#xff0c;保存即可。 在下面的资源文件夹中即可看到添加的图片列表 **方法一&#xff1a;**重绘标签及背景 新建窗体…

WPF 自定义TabControl控件样式(转)

WPF 自定义TabControl控件样式 一、前言 程序中经常会用到TabControl控件&#xff0c;默认的控件样式很普通。而且样式或功能不一定符合我们的要求。比如&#xff1a;我们需要TabControl的标题能够居中、或平均分布&#xff1b;或者我们希望TabControl的标题能够进行关闭。要…

WPF TabControl 数据绑定

WPF TabControl in Binding’s world 首先&#xff0c;TabControl是间接继承自ItemControl的控件&#xff0c;因此可以像ItemControl那样自如的使用。 自此&#xff0c;我们知道了ItemControl的派生控件有&#xff1a; ItemControl–>Selector–>ListBox ItemControl…

WPF TabControl Styles

WPF TabControl Styles 水平使用的TabControl 效果&#xff1a; 样式资源 <!-- 顶部TabControl控件样式 --><SolidColorBrush x:Key"TabItem.Static.Background" Color"White"/><SolidColorBrush x:Key"TabItem.Static.Border&quo…

MFC tabcontrol切换界面

1.添加控件tabcontrol。 2.切换到资源界面->Dialog->插入Dialog&#xff0c;创建两个Dialog界面。 3.为新建的两个Dialog添加类&#xff0c;在新建的Dialog界面右键类向导添加对应的类。 4.添加TabSheet.cpp 和TabSheet.h 这两个文件从网上下载即可&#xff0c;具体源码如…

TabControl控件

点餐用到的控件&#xff1a; 1&#xff09;TabControl: 管理并向用户显示可以包含控件和组件的相关选项卡的信息 2&#xff09;ComboBox: 显示一个可编辑的文本框&#xff0c;其中包含一个允许值下拉列表 3&#xff09;DateTimePicker: 允许用户设定日期和时间&#x…