搜索
首页Javajava教程JVM内存模型与运行时数据区域的详解(图文)

本篇文章给大家带来的内容是关于JVM内存模型与运行时数据区域的详解(图文),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

一、java内存模型

1487783328-5bc4b84f6fbd1_articlex.png

java定义内存模型的目的是:为了屏蔽各种硬件和操作系统的内存访问之间的差异。

java内存模型规定了所有的变量都存储在主内存中,每条线程拥有自己的工作内存,工作内存保存了主内存中变量的副本。

线程对变量操作只能在工作内存中进行,不能直接读写主内存的变量。

不同线程之间的变量访问需要通过主内存来完成。

1、java内存模型和java运行时数据区域的关系:主内存对应着java堆,工作内存对应着java栈。

2、volatile关键字,使得变量的更新在各个工作内存中都是实时可见的。在DCL的单例模式中有运用到

二、java运行时数据区域/内存区域

因为jvm的运行时数据区域一直在改善,所以不同jdk版本之间会有不同。

1、jdk1.7之前的jvm内存区域,拥有永久代

2014176931-5bc4b84f87394_articlex.png

1、程序计数器的作用,因为.java文件被编译成.class文件,它作为当前线程所执行的字节码的行号指示器。当字节码解释器工作时,就是通过改变这个计算器的值来选取下一条要执行的字节码指令。每条线程都有一个独立的程序计数器。

2、本地方法栈就是执行本地native方法的栈,native方法由虚拟机实现!

3、java虚拟机栈描述的是该线程执行java方法(method)时的内存模型。每一个方法都对应一个栈帧,栈帧中的局部变量表存储了方法中的基本数据类型变量、对象引用变量。

3615879256-5bc4b84f79b60_articlex.png

如上图所示,局部变量表保存了方法中声明的8种基本类型变量和对象引用变量。每一个栈帧中还有一个指向运行时常量池的引用,这是指String类型。下面有一个经典的String对象生成的面试题!

4、java堆是JVM中内存最大的一块,被所有线程共享。几乎所有的对象实例都在这里分配,所以java堆也是JVM垃圾回收的主要区域。java堆又被分成了年轻代,老年代;年轻代进一步可以划分为Eden空间,From Survivor空间、To Survivor空间。

3845570429-5bc4b84f1afc4_articlex.png

当我们使用new关键字分配对象时,就是在java堆中生成对象。

下面分析一下对象生成时的情况。

  1. 因为Eden最大,所以新生成的对象都分配到Eden空间,当Eden空间快满时,进行一次Minor GC,然后将存活的对象复制到From Survivor空间。这时,Eden空间继续向外提供堆内存。

  2. 后面继续生成的对象还是放到Eden空间,当Eden空间又要满的时候,这时候Eden空间和From Survivor空间同时进行一次Minor GC,然后把存活对象放到To Survivor空间。这时,Eden空间继续向外提供堆内存。

  3. 接下来的情况和2一致。Eden空间快满的时候,Eden空间和To Survivor空间进行一次Minor GC,然后存活的对象放到From Survivor空间。

  4. 接下来的情况和3一致。Eden空间快慢的时候,Eden空间和From Survivor空间进行一次Minor GC,然后存活的对象放到To Survivor空间。

  5. 就是说2个Survivor中的一个用来提供对象保存。当Eden空间和某一块Survivor空间GC后,另一块Survivor空间放不下GC后存活的对象;或者是连续Minor GC15次左右的情况;就把这部分存活对象放入到老年代空间。

  6. 当老年代空间也放满的时候,进行Major GC,对老年代空间进行回收。(也叫做Full GC,Full GC的内存消耗很大,应该避免)

年轻代使用的是复制算法:每次Minor GC把Eden区和一块Survivor区的存活对象复制到另一块Survivor区。老年代使用的是标记-整理算法:每次Major GC把存活对象都想内存空间的一端移动,然后直接清理掉端边界以外的内存。

大对象如数组、很长的字符串,直接进入老年代空间。

5、方法区用于存储JVM加载的类信息、final常量、static静态变量等数据,方法区中的数据都是整个程序中唯一的。方法区还包含了运行时常量池,主要存放编译期生成的字面量和符号引用(在类加载后放入)。String对象的字面量就会被放入到运行时常量池中。

垃圾回收在方法区主要是对常量的回收和对类型的卸载。

2、jdk1.8及之后的jvm内存区域,元空间取代了永久代

776192883-5bc4b84f01b34_articlex.png

元空间和永久代的性质是一样的,都是对JVM方法区的实现,作用是一样的。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机JVM内存中,而是使用本地内存。

为什么用元空间取代永久代呢?

  1. 字符串存在永久代中,容易出现性能问题和内存溢出。

  2. 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。

  3. 永久代会为GC带来不必要的复杂度,并且回收效率偏低。

直接内存

JDK1.4之后加入的NIO,引入了基于通道channel和缓冲区buffer的IO,直接使用native函数分配堆外内存,显著提高IO性能,避免了原来BIO的在java堆和naive堆中来回复制数据。

1947740664-5bc4b84ef3fc1_articlex.png

3、字符串String生成时的内存分配情况

参考文章:Java中字符串常量池的详解

4、生成对象时的内存情况

下面来分析一下我们常见的生成对象或基本数据类型变量的内存模型。这样可以对JVM有一个更好的理解。

int i =3;,一个方法对应一个栈帧,方法中的基本数据类型变量直接在栈帧中分配。如果是static、final类型的基本数据类型则存储在运行时常量池中,和String一样。

Object o1 = new Object();,对象引用(Object o1)存储在栈帧中,但是对象数据(new Object())存储在java堆中,对象类型数据(Class等信息)存储在方法区中。

String s1 = new String("abcd");,使用new声明的对象,对象引用(String s1)存储在栈帧中,对象数据(new String(“abcd”))存储在java堆中,字符串值(“abcd”)存储在运行时常量池中。

String s2 = “abc”,对象引用(String s2)存储在栈帧中,字符串值(“abc”)存储在运行时常量池中。

3883870872-5bc4b84f0831f_articlex.png

java栈、java堆、方法区这3者之间的关系大概就是上面的分析所示。

3、各种异常分析

1、java堆内存溢出错误OutOfMemoryError

如果java堆中分配的对象太多,且GC后内存空间还是不够用。下面通过循环生成对象来消耗内存空间进行测试。

相关指令:VM Args: -Xms20m -Xmx40m,表示JVM分配的堆内存最小为20MB,最大为40MB。

 public static void main(String[] args) {
   while (true) {
     List<Object> list = new ArrayList<>(10);
     list.add(new Object());
   }
 }

2、java栈堆栈溢出错误StackoverflowError

如果java栈的栈深度大于JVM允许的深度,就会抛出该错误。下面通过无限递归调用来进行堆栈进行测试。

相关指令:VM Args: -Xss128k,表示JVM分配的栈容量为128KB。

public class StackOOM {
    
    private int length = 1;
    
    public void stackLeak() {
        length++;
        stackLeak();
    }
    
    public static void main(String[] args) {
        StackOOM stackOOM = new StackOOM();
        stackOOM.stackLeak();
    }
}

2546966542-5bc4b84f04c85_articlex.png


以上是JVM内存模型与运行时数据区域的详解(图文)的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault思否。如有侵权,请联系admin@php.cn删除
Java开发的哪些方面取决于平台?Java开发的哪些方面取决于平台?Apr 26, 2025 am 12:19 AM

JavadevelovermentIrelyPlatForm-DeTueTososeVeralFactors.1)JVMVariationsAffectPerformanceNandBehaviorAcroSsdifferentos.2)Nativelibrariesviajnijniiniininiinniinindrododerplatefform.3)

在不同平台上运行Java代码时是否存在性能差异?为什么?在不同平台上运行Java代码时是否存在性能差异?为什么?Apr 26, 2025 am 12:15 AM

Java代码在不同平台上运行时会有性能差异。1)JVM的实现和优化策略不同,如OracleJDK和OpenJDK。2)操作系统的特性,如内存管理和线程调度,也会影响性能。3)可以通过选择合适的JVM、调整JVM参数和代码优化来提升性能。

Java平台独立性有什么局限性?Java平台独立性有什么局限性?Apr 26, 2025 am 12:10 AM

Java'splatFormentenceHaslimitations不包括PerformanceOverhead,versionCompatibilityIsissues,挑战WithnativelibraryIntegration,Platform-SpecificFeatures,andjvminstallation/jvminstallation/jvmintenance/jeartenance.therefactorscomplicatorscomplicatethe“ writeOnce”

解释平台独立性和跨平台发展之间的差异。解释平台独立性和跨平台发展之间的差异。Apr 26, 2025 am 12:08 AM

PlatformIndependendecealLowsProgramStormonanyPlograwsStormanyPlatFormWithOutModification,而LileCross-PlatFormDevelopmentRequiredquiresMomePlatform-specificAdjustments.platFormIndependence,EneblesuniveByjava,EnablesuniversUniversAleversalexecutionbutmayCotutionButMayComproMisePerformance.cross.cross.cross-platformd

即时(JIT)汇编如何影响Java的性能和平台独立性?即时(JIT)汇编如何影响Java的性能和平台独立性?Apr 26, 2025 am 12:02 AM

JITcompilationinJavaenhancesperformancewhilemaintainingplatformindependence.1)Itdynamicallytranslatesbytecodeintonativemachinecodeatruntime,optimizingfrequentlyusedcode.2)TheJVMremainsplatform-independent,allowingthesameJavaapplicationtorunondifferen

为什么Java是开发跨平台桌面应用程序的流行选择?为什么Java是开发跨平台桌面应用程序的流行选择?Apr 25, 2025 am 12:23 AM

javaispopularforcross-platformdesktopapplicationsduetoits“ writeonce,runanywhere”哲学。1)itusesbytbytybytecebytecodethatrunsonanyjvm-platform.2)librarieslikeslikeslikeswingingandjavafxhelpcreatenative-lookingenative-lookinguisis.3)

讨论可能需要在Java中编写平台特定代码的情况。讨论可能需要在Java中编写平台特定代码的情况。Apr 25, 2025 am 12:22 AM

在Java中编写平台特定代码的原因包括访问特定操作系统功能、与特定硬件交互和优化性能。1)使用JNA或JNI访问Windows注册表;2)通过JNI与Linux特定硬件驱动程序交互;3)通过JNI使用Metal优化macOS上的游戏性能。尽管如此,编写平台特定代码会影响代码的可移植性、增加复杂性、可能带来性能开销和安全风险。

与平台独立性相关的Java开发的未来趋势是什么?与平台独立性相关的Java开发的未来趋势是什么?Apr 25, 2025 am 12:12 AM

Java将通过云原生应用、多平台部署和跨语言互操作进一步提升平台独立性。1)云原生应用将使用GraalVM和Quarkus提升启动速度。2)Java将扩展到嵌入式设备、移动设备和量子计算机。3)通过GraalVM,Java将与Python、JavaScript等语言无缝集成,增强跨语言互操作性。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具