jvm深入研究文档--jvm分区以及职责

2023-09-20 14:46:43

Java虚拟机(JVM)主要包括以下几个区域:

  1. 方法区(Method Area):这个区域存储已被加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。方法区是所有线程共享的。在Java 8之前,方法区是永久代(PermGen),从Java 8开始,永久代被元空间(Metaspace)替代。
  2. 堆区(Heap):这是Java内存中最大的一块区域,被所有线程共享,用于存放对象实例。JVM在JDK 1.7之前,使用的是分代收集(Generational Collection),包括新生代(Young Generation)和老年代(Old Generation)。在JDK 1.8之后,引入了Eden Space, Survivor Space和Old Generation的概念。
  3. 栈区(Stack):每个线程在创建时都会创建一个虚拟机栈,每一个方法执行的时候都会创建一个栈帧用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
  4. 程序计数器(Program Counter Register):这个区域可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。
  5. 本地方法栈(Native Method Stack):与虚拟机栈所发挥的作用非常相似,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。

每个JVM分区在不同版本的Java中都可能有所变更,特别是在每次大版本更新时,例如Java 8、Java 11和Java 17中都进行了一些重要的变更。

方法区(Method Area)

方法区(Method Area)是Java虚拟机(JVM)中的一部分,它与Java堆一样,是各个线程共享的内存区域。在JVM启动时方法区被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。

虽然方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。因此,方法区可以看作是一块独立于Java堆的内存空间。

此外,方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误。

堆区(Heap)

堆区是Java虚拟机(JVM)中的主要部分,也是垃圾收集的主要区域。它主要用于存放对象实例以及大多数Java对象(如数组,用户定义的类等)。

在Java堆中,对象的内存分配和回收是主要发生的地方。当你创建一个新的对象实例时,JVM会在堆上为其分配内存。当对象不再被引用时,垃圾收集器会回收其占用的内存。

Java堆是所有线程共享的,因此它是一个并发区域,也就是说在任何时刻,多个线程可能同时对同一个对象进行操作。

Java堆是垃圾收集的主要区域,这意味着垃圾收集器可以自动回收不再被引用的对象占用的内存。这极大地减少了内存泄漏的可能性,因为JVM会自动管理内存,避免内存泄漏。

栈区(Stack)

栈区是Java虚拟机(JVM)中的另一个重要部分,与堆区不同的是,栈区只属于某一个特定的线程,是线程私有的。每个线程都会有一个对应的栈,它的生命周期与线程的生命周期一致。

栈区主要用于执行Java方法,每一个方法的执行都会创建一个栈帧,用于存储局部变量、操作数栈以及动态链接和方法出口等信息。当一个方法执行完成后,对应的栈帧就会被弹出,所占用的内存会被释放。

栈区的容量也是有限制的,如果程序中创建了大量的栈帧并且没有被及时回收,那么就会出现栈溢出的情况,这时候程序会抛出一个StackOverflowError错误。在Java中,可以通过-Xss参数来设置每个线程的栈大小。

程序计数器(Program Counter Register)

程序计数器(Program Counter Register)是计算机处理器中的一种特殊寄存器。它的主要功能是跟踪并存储当前正在执行的指令在内存中的地址。

在计算机的执行过程中,程序计数器会根据指令的执行顺序进行更新。每执行一条指令,程序计数器就会增加,指向下一条要执行的指令。当遇到跳转指令(如JMP,CALL等)时,程序计数器会直接跳转到指定的地址,改变当前执行顺序。

程序计数器通常被视为CPU的“眼睛”,它知道下一步应该执行哪条指令,是CPU执行流程的关键部分。

PC寄存器是线程私有的,每一个线程都有一个独立的PC寄存器。它的生命周期和线程保持一致,随着线程的创建和销毁而存在。

在JVM中,PC寄存器也是线程私有的,它用来存储JVM字节码指令的地址。JVM的字节码解释器通过改变PC寄存器的值来明确下一条要执行的字节码指令。

PC寄存器的设定是为了能够准确的记录各个线程正在执行的当前字节码指令地址,以便CPU在需要在线程之间切换时,可以快速准确地找到下一条要执行的指令。

本地方法栈(Native Method Stack)

本地方法栈(Native Method Stack)是Java虚拟机(JVM)中的一部分,与Java堆和栈区一起构成了Java运行时环境。

本地方法栈和Java栈一样,都是线程私有的,它用于支持native方法的执行。在Java中,如果一个方法使用了native修饰符,那么这个方法就会在本地方法栈中执行。

本地方法栈和Java栈的主要区别在于,本地方法栈中的方法可以执行操作系统级别的调用,例如访问文件系统、网络资源等。因此,本地方法栈具有更高的灵活性和更大的风险,因为它可以直接访问物理资源。

本地方法栈的管理和垃圾收集方式与Java堆和栈区不同,它的回收和内存管理需要更复杂的技术来实现。如果本地方法栈中的内存泄漏或者溢出,会对整个JVM的性能产生影响。

更多推荐

论如何在Android中还原设计稿中的阴影

每当设计稿上注明需要添加阴影时,Android上总是显得比较棘手,因为Android的阴影实现方式与Web和iOS有所区别。一般来说阴影通常格式是有:X:在X轴的偏移度Y:在Y轴偏移度Blur:阴影的模糊半径Color:阴影的颜色何为阴影但是在Android中却比较单一,只有一个度量单位:Elevation,作为在An

ELK 企业级日志分析系统 ELFK

一、概述ELK平台是一套完整的日志集中处理解决方案,将ElasticSearch、Logstash和Kiabana三个开源工具配合使用,完成更强大的用户对日志的查询、排序、统计需求。使用ELK日志文件系统的原因:日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过

ELK集群部署

目录ELKElasticsearch集群部署部署Elasticsearch软件安装Elasticsearch-head插件ELKLogstash部署ELKKiabana部署Filebeat+ELK部署ELKElasticsearch集群部署Node1节点(2C/4G):node1/192.168.233.30Elast

浅谈C++|STL之list+forward_list篇

一.list基本概念功能:将数据进行链式存储链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的链表的组成:链表由—系列结点组成结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域STL中的链表是一个双向循环链表由于链表的存储方式并不是连续的内存空间

阿里云无影云电脑详细介绍:价格、使用和功能优势说明

什么是阿里云无影云电脑?无影云电脑(原云桌面)是一种快速构建、高效管理桌面办公环境,无影云电脑可用于远程办公、多分支机构、安全OA、短期使用、专业制图等使用场景,阿里云百科分享无影云桌面的详细介绍、租用价格、云电脑的优势、使用场景、网络架构、无影云电脑与云服务器的区别以及关于无影云电脑的常见问题解答FAQ:目录阿里云无

华为云云耀云服务器L实例评测|用PHP从数据库到后端到前端完整实现一个中秋节祝福语项目

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。🏆本文已收录于PHP专栏:PHP进阶实战教程,评测专区。🎉欢迎👍点赞✍评论⭐收藏文章目录🚀一、前言🚀二、

TCP详解之重传机制

TCP详解之重传机制TCP实现可靠传输的方式之一,是通过序列号与确认应答。在TCP中,当发送端的数据到达接收主机时,接收端主机会返回一个确认应答消息,表示已收到消息。但在错综复杂的网络,并不一定能如上图那么顺利能正常的数据传输,万一数据在传输过程中丢失了呢?所以TCP针对数据包丢失的情况,会用重传机制解决。接下来说说常

【C++】C++11(列表初始化和右值引用)

前言:C++的发展其实并不是一蹴而就的,他经历了很多阶段,本章开始,我们将进入C++11的学习。我们大致来看一下C++的发展历程:当然在这些之中还发行了其他的版本,C++还在不断的向后发展。但是:现在公司主流使用还是C++98和C++11。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新

尚硅谷wepack课程学习笔记

为什么需要使用打包工具?开发时使用的框架、es6语法、less等浏览器无法识别。需要经过编译成浏览器能识别的css、js才可以运行。打包工具可以帮我们编译,号可以做代码压缩、兼容处理、性能优化。常见的打包工具有什么?vite、webpack、glup、gruntwebapck最基本的使用?是一个静态资源打包工具,以一个

@Valid注解的作用及@Valid注解与@Validated的区别

1.@Valid注解导入依赖<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId></dependency><dependency><groupId>org.hibernate.validator</g

面试官:你是怎么理解ES6中Proxy的?使用场景?

🎬岸边的风:个人主页🔥个人专栏:《VUE》《javaScript》⛺️生活的理想,就是为了理想的生活!目录一、介绍二、用法参数handler解析Reflectget()set()deleteProperty()取消代理三、使用场景一、介绍定义:用于定义基本操作的自定义行为本质:修改的是程序默认形为,就形同于在编程语

热文推荐