服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

2021-12-15 11:09苍何fly Java教程

这篇文章主要介绍了JVM运行时数据区划分原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、前言

这是JVM系列文章的第三篇,这篇文章将对整个JVM运行时数据区和GC垃圾回收详细的介绍。这部分也算是JVM的核心内容了。

 

二、运行时数据区整体概架构

JAVA JVM运行时数据区详解

以下是自己的一句话总结:

分为线程私有和线程共享的两大类,其中程序计数器、虚拟机栈、本地方法栈是属于线程私有的,堆内存及方法区内存是线程共享的。程序计数器主要是记录字节码指令,CPU上下文切换线程,从一个线程切换到另一个线程,需要知道线程执行到哪一步,所以记录这个指令就是很有必要的,程序计数器无OOM和GC的发生。虚拟机栈里面是一个个栈帧,每一个栈帧对应着每一个方法,栈帧又是由局部变量表、操作数栈、方法返回值地址、动态链接组成。虚拟机栈可能会发生栈溢出异常,即starkoverflow本地方法栈是存放本地方法相关的东西;堆是一块很大的空间,整体分为2大块,新生代和老年代,新生代又分了Eden区、S0区、S1区,垃圾回收主要发生在新生代,每一个区对应不同的垃圾回收算法;方法区保存的是一些常量、类的基本信息等,方法区对应的实现在JDK7中是永久代,在JDK8中是元空间。

 

三、程序计数器

用来储存指向下一条指令的地址,是线程私有的,生命周期和线程的生命周期一致。

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

 

四、虚拟机栈

虚拟机栈是线程私有的,内部保存一个个栈帧,每一个栈帧对应一个Java方法的调用,生命周期和线程的生命周期保持一致。先来看看栈的特点。

JAVA JVM运行时数据区详解

1、栈的特点

栈是运行时的单位,而堆是存储的单位。栈的特点是先进后出,后进先出。

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

可以通过参数-Xss来设置栈空间大小

2、栈帧的内部结构

JAVA JVM运行时数据区详解

3、局部变量表

是一个数字数组,主要用于存储方法参数和定义在方法内的局部变量,这些数据类型包括各类基本数据类型,对象引用等,所需的容量大小是在编译期确定下来的,在方法运行期间是不会改变局部变量表大小的。

关于Slot的理解:

JAVA JVM运行时数据区详解

静态变量和局部变量的区别:

JAVA JVM运行时数据区详解

总结:

在栈帧中,与性能关系最为密切的就是局部变量表,在方法执行时,虚拟机使用局部变量表完成完成方法的传递,局部变量表中的数据也是可达性分析中的GC Root,如果一个对象在局部变量表中还有引用,那么根绝可达性分析算法,这个变量就不属于垃圾对象,是不会被GC回收的。

4、操作数栈

操作数栈是栈中栈,也可称为表达式栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈和出栈。主要用于保存计算过程的中间结果。操作数栈,可以看成是临时寄存器,计算过程中变量的临时保存

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

5、动态链接

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

方法重写的本质

JAVA JVM运行时数据区详解

6、方法返回地址

存放调用该方法的PC寄存器的值

JAVA JVM运行时数据区详解

 

五、本地方法栈

管理本地native本地方法,是线程私有的,所谓的本地方法,其实就是一些非Java语言写的代码,这部分代码甚至可以和操作系统CPU进行打交道。

 

六、堆

堆是内存管理的核心区域,是线程共享的,属于JVM级别,也就是一个JVM实例就会有一个堆空间,注意的是虽然堆整体上是线程共享的,但是在内部有一小块空间是线程私有的缓存区TLAB。

几乎所有的对象实例都是在堆中,堆是GC垃圾回收的重点区域。堆整体可以分为新生代和老年代,新生代又分为Eden区和S0和S1区。

JAVA JVM运行时数据区详解

新生代和老年代的比例是1:2,Eden区和s0,s1区所占空间比例是8:1:1

1、设置堆大小的参数

-Xms:用于表示堆区的起始内存,默认情况下,占物理内存大小的64分之一。

-Xmx用于表示堆区的最大内存,默认情况下,占物理内存的四分之一。

通常起始内存和最大内存两个参数设置成一样,目的是为了GC清理完堆区内存后不需要重新分隔
计算堆区的大小,从而提高性能。
查看设置的参数:
方式一:jps(查看进程)  
          jstat -gc 进程id
方式二:-xx:+printGCDetails

2、对象分配过程

JAVA JVM运行时数据区详解

这里s0和s1谁是空的谁就是to,年龄计数器阈值是15,YGC是在Eden区满的时候会触发,s0和s1满的时候不会触发YGC,YGC会将s区以及伊甸园区一起GC

关于垃圾回收,频繁在新生区收集,很少在养老区收集,几乎不在永久区/元空间收集。

JAVA JVM运行时数据区详解

Visualvm是JVM常用调优工具,在JDK的bin下就可以打开

3、堆中的GC

JAVA JVM运行时数据区详解

年轻代(Minor GC)触发机制

JAVA JVM运行时数据区详解

老年代GC(Major GC/Full GC)触发机制

Full GC 触发机制

JAVA JVM运行时数据区详解

4、内存分配策略

JAVA JVM运行时数据区详解

5、什么是TLAB

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

TLAB表明堆不一定是共享的。

6、堆是分配对象存储的唯一选择吗?

如果经过逃逸分析,一个对象并没有逃逸出方法的话,那么就有可能被优化成栈上分配。

逃逸分析手段:

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

注意:JDK6U23版本后,HotSpot默认已经开启逃逸分析。所以我们得出一个结论,开发中能使用局部变量的,就不要使用在方法外定义。JDK7后字符串常量池和静态变量存储在堆中

 

七、方法区

方法区可以看做是一块独立于堆的内存空间,是线程共享的,主要存储类信息、运行时常量池等,也会发生OOM,JDK8前成为永久代,JDK8成为元空间。(元空间和永久代最大的区别是,元空间不再使用JVM内存,而是使用了本地内存技术)

1、方法区概述

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

2、设置方法区内存大小

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

3、如何解决OOM问题?

JAVA JVM运行时数据区详解

4、方法区存储什么

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

5、方法区的演进细节

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

6、方法区的GC

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

JAVA JVM运行时数据区详解

 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/qq_43270074/article/details/120038391

延伸 · 阅读

精彩推荐
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08