Java程序员必备基础结构图

article/2025/10/10 18:18:10

前言

最近看了深入理解Java虚拟机第三版,整理了一些基础结构图,算是比较全的了,做一下笔记,大家一起学习。

1.Java虚拟机运行时数据区图


JVM内存结构是Java程序员必须掌握的基础。

程序计数器

  • 程序计数器,可以看作当前线程所执行的字节码的行号指示器
  • 它是线程私有的。

Java虚拟机栈

  • 线程私有的,生命周期与线程相同。
  • 每个方法被执行的时候都会创建一个"栈帧",用于存储局部变量表(包括参数)、操作数栈、动态链接、方法出口等信息。
  • 局部变量表存放各种基本数据类型boolean、byte、char、short等

本地方法栈

  • 与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。

Java堆

  • Java堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,在JVM启动时创建。
  • 其大小通过-Xms和-Xmx参数设置,-Xms为JVM启动时申请的最小内存,-Xmx为JVM可申请的最大内存。

方法区

  • 它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。
    -可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小。

2. 堆的默认分配图

  • Java堆 = 老年代 + 新生代
  • 新生代 = Eden + S0 + S1
  • 新生代与老年代默认比例的值为 1:2 ,可以通过参数 –XX:NewRatio 配置。
  • 默认的,Eden : from : to = 8 : 1 : 1 ,可以通过参数–XX:SurvivorRatio 来设定

3.方法区结构图

方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

4.对象的内存布局图

一个Java对象在堆内存中包括对象头、实例数据和补齐填充3个部分:

  • 对象头包括Mark Word(存储哈希码,GC分代年龄等) 和 类型指针(对象指向它的类型元数据的指针),如果是数组对象,还有一个保存数组长度的空间
  • 实例数据是对象真正存储的有效信息,包括了对象的所有成员变量,其大小由各个成员变量的大小共同决定。
  • 对齐填充不是必然存在的,仅仅起占位符的作用。

5.对象头的Mark Word图

  • Mark Word 用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等。
  • 在32位的HotSpot虚拟机中,如果对象处于未被锁定的状态下,那么Mark Word的32bit空间里的25位用于存储对象哈希码,4bit用于存储对象分代年龄,2bit用于存储锁标志位,1bit固定为0,表示非偏向锁。

6.对象与Monitor关联结构图

对象是如何跟monitor有关联的呢?

一个Java对象在堆内存中包括对象头,对象头有Mark word,Mark word存储着锁状态,锁指针指向monitor地址。这其实是Synchronized的底层哦~

7.Java Monitor的工作机理图:

Java 线程同步底层就是监视锁Monitor~,如下是Java Monitor的工作机理图:

  • 想要获取monitor的线程,首先会进入_EntryList队列。
  • 当某个线程获取到对象的monitor后,进入_Owner区域,设置为当前线程,同时计数器_count加1。
  • 如果线程调用了wait()方法,则会进入_WaitSet队列。它会释放monitor锁,即将_owner赋值为null,_count自减1,进入_WaitSet队列阻塞等待。
  • 如果其他线程调用 notify() / notifyAll() ,会唤醒_WaitSet中的某个线程,该线程再次尝试获取monitor锁,成功即进入_Owner区域。
  • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁。

8.创建一个对象内存分配流程图

  • 对象一般是在Eden区生成。
  • 如果Eden区填满,就会触发Young GC。
  • 触发Young GC的时候,Eden区实现清除,没有被引用的对象直接被清除。
  • 依然存活的对象,会被送到Survivor区,Survivor =S0+S1.
  • 每次Young GC时,存活的对象复制到未使用的那块Survivor 区,当前正在使用的另外一块Survivor 区完全清除,接着交换两块Survivor 区的使用状态。
  • 如果Young GC要移送的对象大于Survivor区上限,对象直接进入老年代。
  • 一个对象不可能一直呆在新生代,如果它经过多次GC,依然活着,次数超过-XX:MaxTenuringThreshold的阀值,它直接进入老年代。简言之就是,对象经历多次滚滚长江,红尘世事,终于成为长者(进入老年代)

9.可达性分析算法判定对象存活

可达性分析算法是用来判断一个对象是否存活的~

算法的核心思想:

  • 通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始根据引用关系向下搜索,搜索走过的路径称为“引用链”,当一个对象到 GC Roots 没有任何的引用链相连时(从 GC Roots 到这个对象不可达)时,证明此对象不可能再被使用。

10.标记-清除算法示意图

  • 标记-清除算法是最基础的垃圾收集算法。
  • 算法分为两个阶段,标记和清除。
  • 首先标记出需要回收的对象,标记完成后,统一回收掉被标记的对象。
  • 当然可以反过来,先标记存活的对象,统一回收未被标记的对象。
  • 标记-清除 两个缺点是,执行效率不稳定和内存空间的碎片化问题~

11.标记-复制算法示意图

  • 1969年 Fenichel提出“半区复制”,将内存容量划分对等两块,每次只使用一块。当这一块内存用完,将还存活的对象复制到另外一块,然后把已使用过的内存空间一次清理掉~
  • 1989年,Andrew Appel提出“Appel式回收”,把新生代划分为较大的Eden和两块较小的Survivor空间。每次分配内存只使用Eden和其中一块Survivor空间。发生垃圾收集时,将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上。Eden和Survivor比例是8:1~
  • “半区复制”缺点是浪费可用空间,并且,如果对象存活率高的话,复制次数就会变多,效率也会降低。

12.标记-整理算法示意图

  • 1974年,Edward 提出“标记-整理”算法,标记过程跟“标记-清除”算法一样,接着让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存~
  • 标记-清除算法和标记整理算法本质差异是:前者是一种非移动式的回收算法,后者是移动式的回收算法。
  • 是否移动存活对象都存在优缺点,移动虽然内存回收复杂,但是从程序吞吐量来看,更划算;不移动时内存分配更复杂,但是垃圾收集的停顿时间会更短,所以看收集器取舍问题~
  • Parallel Scavenge收集器是基于标记-整理算法的,因为关注吞吐。CMS收集器是基于标记-清除算法的,因为它关注的是延迟。

13.垃圾收集器组合图

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:CMS、Serial Old、Parallel Old
  • 混合收集器:G1

14.类的生命周期图

一个类从被加载到虚拟机内存开始,到卸载出内存为止,这个生命周期经历了七个阶段:加载、验证、准备、解析、初始化、使用、卸载。

加载阶段:

  • 通过一个类的全限定名来获取定义此类的二进制字节流。
  • 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
  • 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口

验证:

  • 验证的目的是确保Class文件的字节流中包含的信息满足约束要求,保证这些代码运行时不会危害虚拟机自身安全
  • 验证阶段有:文件格式校验、元数据校验、字节码校验、符号引用校验。

准备

  • 准备阶段是正式为类中定义的变量(静态变量)分配内存并设置类变量初始值的阶段。

解析

  • 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。

初始化

  • 到了初始化阶段,才真正开始执行类中定义的Java字节码。

15.类加载器双亲委派模型图

双亲委派模型构成

启动类加载器,扩展类加载器,应用程序类加载器,自定义类加载器

双亲委派模型工作过程是

如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即ClassNotFoundException),子加载器才会尝试自己去加载。

为什么需要双亲委派模型?

如果没有双亲委派,那么用户是不是可以自己定义一个java.lang.Object的同名类,java.lang.String的同名类,并把它放到ClassPath中,那么类之间的比较结果及类的唯一性将无法保证,因此,双亲委派模型可以防止内存中出现多份同样的字节码。

16.栈帧概念结构图

栈帧是用于支持虚拟机进行方法调用和方法执行背后的数据结构。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址信息。

局部变量表

  • 是一组变量值的存储空间,用于存放方法参数和方法内部定义的局部变量。
  • 局部变量表的容量以变量槽(Variable Slot)为最小单位。

操作数栈

  • 操作数栈,也称操作栈,是一个后入先出栈。
  • 当一个方法刚刚开始执行的时候, 该方法的操作数栈也是空的, 在方法的执行过程中, 会有各种字节码指令往操作数栈中写入和提取内容, 也就是出栈与入栈操作。

动态连接

  • 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用, 持有引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。

方法返回地址

  • 当一个方法开始执行时, 只有两种方式退出这个方法 。一种是执行引擎遇到任意一个方法返回的字节码指令。另外一种退出方式是在方法执行过程中遇到了异常。

17.Java内存模型图

  • Java内存模型规定了所有的变量都存储在主内存中
  • 每条线程还有自己的工作内存
  • 线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝
  • 线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。
  • 不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

18.线程状态转换关系图


Java语言定义了6种线程池状态:

  • 新建(New):创建后尚未启动的线程处于这种状态
  • 运行(Running):线程开启start()方法,会进入该状态。
  • 无限等待(Waiting):处于这种状态的线程不会被分配处理器执行时间,一般LockSupport::park(),没有设置了Timeoout的Object::wait()方法,会让线程陷入无限等待状态。
  • 限期等待(Timed Waiting):处于这种状态的线程不会被分配处理器执行时间,在一定时间之后他们会由系统自动唤醒。sleep()方法会进入该状态~
  • 阻塞(Blocked):在程序等待进入同步区域的时候,线程将进入这种状态~
  • 结束(Terminated):已终止线程的线程状态,线程已经结束执行

19. Class文件格式图

  • u1、u2、u4、u8 分别代表1个字节、2个字节、4个字节和8个字节的无符号数
  • 表是由多个无符号数或者其他表作为数据项构成的复合数据类型
  • 每个Class文件的头四个字节被称为魔数(记得以前校招面试,面试官问过我什么叫魔数。。。)
  • minor和major version表示次版本号,主版本号
  • 紧接着主次版本号之后,是常量池入口,常量池可以比喻为Class文件里的资源仓库~

20.JVM参数思维导图

JVM调优是通往高级开发的必经桥梁,所以好好积累JVM参数配置哈~

个人公众号

  • 如果你是个爱学习的好孩子,可以关注我公众号,一起学习讨论。
  • 如果你觉得本文有哪些不正确的地方,可以评论,也可以关注我公众号,私聊我,大家一起学习进步哈。

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

相关文章

JVM 结构图

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

JVM结构、GC工作机制详解

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

详解 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问题(记忆集)3.5 G1两种回收策略4. G1收集器优缺点 5. G1收集器核心配置参数 1. 什么是G1 G1…

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

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

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…

WPF 控件专题 TabControl控件详解

1、TabControl 介绍 TabControl 表示包含多个项的控件&#xff0c;这些项共享屏幕上的同一空间&#xff0c;每个区域都可以通过单击通常位于控件顶部的选项卡标题来访问。 也叫选项卡控件。 *******************************************************************************…

WPF 基础控件之 TabControl样式

其他基础控件 1.Window2.Button3.CheckBox4.ComboBox5.DataGrid 6.DatePicker7.Expander8.GroupBox9.ListBox10.ListView11.Menu12.PasswordBox13.TextBox14.RadioButton15.ToggleButton16.Slider 17.TreeView TabControl 实现下面的效果 1&#xff09;TabControl来实现动画&…

WPF TabControl美化

实现效果 XMAL样式 <Window.Resources><!-- TabItem的样式 --><Style TargetType"{x:Type TabItem}"><Setter Property"Template"><Setter.Value><ControlTemplate TargetType"{x:Type TabItem}"><Gr…

WPF动态加载TabControl

主要讲一下如何通过点击菜单&#xff0c;实现动态加载TabControl的功能&#xff0c;准确来说应该是动态加载TabItem,要实现这个功能&#xff0c;我们需要解决两个问题&#xff1a; 点击菜单的时候&#xff0c;需要传进来一个你要加载的UserControl控件的名称&#xff0c;让程序…