JVM内存模型

威哥有2个月没有写博客了,动手写写JVM内存模型,也当做是自己成长的笔记。

JVM:Java Virtual Machine,即Java虚拟机,用于运行Java程序编译后的字节码文件。java运行环境的一部分,是一个虚构出来的计算机,它是通过在实际的计算机上仿真模拟各种计算机功能来实现的。即一次编写,到处运行。

当我们写java代码时,实际上是写.java文件,之后通过编译器编译威.class文件,然后通过ClassLoader(类加载器)把类信息加载到JVM中。最后JVM再调用操作系统,这样就实行了跨平台。

.java文件如下:

.java文件可以通过IDEA编译威.class文件或者提供javac编译。

在介绍JVM内存模型前,我们先理一下JVM的种类,以及Java的堆和栈的概念。

JVM:Java虚拟机,主要有3种,如下。

1、Sun公司的HotSpot 是目前使用范围最广的Java虚拟机。
2、BEA公司的JRockit(原来的 Bea JRockit)电脑软件,系列产品是一个全面的Java运行时解决方案组合。
3、IBM公司的J9 VM 是一个高性能的企业级 Java 虚拟机。

Java 把内存划分成两种:

1、一种是栈内存;

2、另一种是堆内存。

栈:

栈中主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char)和对象句柄(引用类型变量)。

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

威哥这里解释下什么是:引用类型变量?

如:ShopComment model = new ShopComment();

model就是引用类型变量,该变量的引用指向的堆中new出来的对象实体。

优点:存取速度比堆要快,仅次于寄存器,栈数据可以共享。

缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

堆:

用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。

理解了堆和栈,我们接着来看JVM内存模型,下面是威哥画好的一张JVM内存模型图:

1、方法区(Method Area):
方法区主要是放类似类定义、常量、编译后的代码、静态变量等。在JDK1.7中,HotSpot VM的实现就是将其放在永久代中,这样的好处就是可以直接使用堆中的GC算法来进行管理,但坏处就是经常会出现内存溢出,即PermGen Space异常,所以在JDK1.8中,HotSpot VM取消了永久代,用元空间取而代之,元空间直接使用本地内存,理论上电脑有多少内存它就可以使用多少内存,所以不会再出现PermGen Space异常。

威哥这里稍微解释下PermGen Space:

PermGen space的全称是Permanent Generation space,是指内存的永久保存bai区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被du放到PermGen space中,它和存放类实例(Instance)的Heap区域不zhi同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误。

2、堆(Heap):
几乎所有对象、数组等都是在此分配内存的,在JVM内存中占的比例也是极大的,也是GC垃圾回收的主要阵地,平时我们说的什么新生代、老年代、永久代也是指的这片区域。

3、虚拟机栈(Java Stack):
当JVM在执行方法时,会在此区域中创建一个栈帧来存放方法的各种信息,比如返回值,局部变量表和各种对象引用等,方法开始执行前就先创建栈帧入栈,执行完后就出栈。

4、本地方法栈(Native Method Stack):
和虚拟机栈类似,不过区别是专门提供给Native方法用的。

Native方法:一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C,或者C++。

5、程序计数器(Program Counter Register):
占用很小的一片区域,我们知道JVM执行代码是一行一行执行字节码,所以需要一个计数器来记录当前执行的行数。

6、执行引擎:

关于此点,威哥也没有太专业的学术名称解决,大概的意思就是,JVM 解释执行Java字节码指令,即调用字节码指向得本地机器码。

7、本地接口库:

Java本地接口(JNI)是为java编写本地方法和jvm嵌入本地应用程序的标准的应用程序接口。首要的目标是在给定的平台上通过所有的jvm来实现兼容的二进制编码本地方法库。本地接口的作用是融合不同的编程语言为Java所用,它最初的初衷是融合C/C++程序。

8、本地方法库:

此处就不做过多解释,大家都是程序猿,当然知道本地接口库的接口调用的是真实的实行子类,那就是这个了。

 

 

 

JVMJava Virtual Machine)即Java虚拟机,是一种用于计算设备的规范,它是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现 [^1]。JVM内存模型主要包含以下几个部分: ### 程序计数器 程序计数器用于记录当前执行的指令地址。如果程序执行的是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令地址;若正在执行的是一个本地(native,由C语言编写完成)方法,则计数器的值为Undefined。由于它只是记录当前指令地址,不存在内存溢出的情况,是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域 [^5]。 ### JavaJava堆是Java代码可及的内存,是留给开发人员使用的。堆用于存储对象实例及数组值,Java中所有通过new创建的对象的内存都在此分配,堆区由所有线程共享。Heap中对象所占用的内存由GC进行回收。在32位操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过 -Xms 和 -Xmx 来控制。-Xms 为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx 为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB。默认当空余堆内存小于40%时,JVM会增大Heap到 -Xmx 指定的大小,可通过 -XX:MinHeapFreeRatio= 来指定这个比例;当空余堆内存大于70%时,JVM会减小Heap的大小到 -Xms 指定的大小,可通过 -XX:MaxHeapFreeRatio= 来指定这个比例。对于运行系统而言,为避免在运行时频繁调整Heap的大小,通常将 -Xms 和 -Xmx 的值设成一样 [^2][^3]。 ### 非堆(Non - Heap) 非堆是JVM留给自己用的,方法区、JVM内部处理或优化所需的内存 (如JIT编译后的代码缓存)、每个类结构 (如运行时常量池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中 [^2]。 ### Java虚拟机栈 Java虚拟机栈是描述Java方法运行过程的内存模型。它会为每一个即将运行的Java方法创建“栈帧”,用于存储该方法在运行过程中所需要的一些信息,包括局部变量表(存放基本数据类型变量、引用类型的变量、returnAddress类型的变量)、操作数栈、动态链接、当前方法的常量池指针、当前方法的返回地址、方法出口等信息 [^4]。 ### 示例代码展示栈帧概念 ```java public class StackFrameExample { public static int add(int a, int b) { int result = a + b; return result; } public static void main(String[] args) { int x = 5; int y = 3; int sum = add(x, y); System.out.println("Sum: " + sum); } } ``` 在上述代码中,`main` 方法和 `add` 方法在执行时,Java虚拟机栈会分别为它们创建栈帧,用于存储各自运行过程中的信息。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值