JVM学习笔记之初识JVM(三)

news/2024/7/7 10:56:51

一、JVM在计算机中的位置

JVM调用操作系统,操作系统调用硬件,硬件反馈信息至操作系统,操作系统反馈信息至JVM

 

 

 

二、JVM的体系结构

JVM在执行过程中对内存的管理分为5个区域:

1.PC寄存器

2.Java虚拟机栈(JVM Stack)

3.本地方法栈(Native Method Stack)

4.Java 堆内存(Java Heap)

5.方法区(Method Area)

 

三、JVM区域按照功能图解

 

四、JVM区域按照内存是否共享图解

五、JVM体系结构

1.类装载器(ClassLoader)(用来装载.class文件)

2.执行引擎(执行字节码,或者执行本地方法)

3.运行时数据区(方法区、堆、java栈、PC寄存器、本地方法栈)

 

1、程序计数器

程序计数器(Program Counter Register)是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器。

每一条JVM线程都有自己的PC寄存器,在任意时刻一条JVM线程只会执行一个方法的代码。

该方法称为该线程的当前方法(Current Method)如果该方法是java方法,那PC寄存器保存JVM正在执行的字节码指令的地址,如果该方法是native(非Java写的方法),那PC寄存器的值是undefined(导入的C++等其他语言实现方法无法管理指令地址)。

程序计数器内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域

2、Java 虚拟机栈

Java虚拟机栈也是线程私有的,每一条线程都拥有自己私有的Java虚拟机栈,它与线程同时创建,并且生命周期与线程相同。

它描述了Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至完成的过程,都对应一个栈帧从入栈到出栈的过程。关于栈帧详细的内容在后边复习虚拟机字节码执行引擎的时候再说吧。 

Java 虚拟机栈在方法调用和返回中也扮演了很重要的角色。因为除了栈帧的入栈和出栈之外,Java虚拟机栈不会再受其它因素的影响,因此栈帧可在系统的堆上分配内存注意,是系统的Heap而不是Java Heap)。Java虚拟机栈所使用的内存不需要保证是连续的。

详细见《JVM体系结构之四:虚拟机栈VM stack》 

3、本地方法栈

Java可以通过java本地接口JNI(Java Native Interface)来调用其它语言编写(如C)的程序,在Java里面用native修饰符来描述一个方法是本地方法。本地方法栈就是虚拟机线程调用Native方法执行时的栈,它与虚拟机栈发挥类似的作用。但是要注意,虚拟机规范中没有对本地方法栈作强制规定,虚拟机可以自由实现,所以可以不是字节码。如果是以字节码实现的话,虚拟机栈本地方法栈就可以合二为一,事实上,OpenJDK和SunJDK所自带的HotSpot虚拟机就是直接将虚拟机栈和本地方法栈合二为一的。

Java虚拟机规范规定该区域也可抛出StackOverFlowError和OutOfMemoryError。

4、Java 堆

这个区域用来放置所有对象实例以及数组。不过在JIT(Just-in-time)情况下有些时候也有可能在栈上分配对象实例。堆也是java垃圾收集器管理的主要区域(所以很多时候会称它为GC堆)。

从GC回收的角度看,由于现在GC基本都是采用的分代收集算法,所以堆内存结构还可以分块成:新生代和老年代;再细一点的有Eden空间、From Survivor空间、To Survivor空间等。如下图:

2、Java 虚拟机栈

Java虚拟机栈也是线程私有的,每一条线程都拥有自己私有的Java虚拟机栈,它与线程同时创建。并且生命周期与线程相同。它描述了Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至完成的过程,都对应一个栈帧从入栈到出栈的过程。关于栈帧详细的内容在后边复习虚拟机字节码执行引擎的时候再说吧。 
Java 虚拟机栈在方法调用和返回中也扮演了很重要的角色。因为除了栈帧的入栈和出栈之外,Java虚拟机栈不会再受其它因素的影响,因此栈帧可在系统的堆上分配内存(注意,是系统的Heap而不是Java Heap)。Java虚拟机栈所使用的内存不需要保证是连续的。

详细见《JVM体系结构之四:虚拟机栈VM stack》

 

3、本地方法栈

Java可以通过java本地接口JNI(Java Native Interface)来调用其它语言编写(如C)的程序,在Java里面用native修饰符来描述一个方法是本地方法。本地方法栈就是虚拟机线程调用Native方法执行时的栈,它与虚拟机栈发挥类似的作用。但是要注意,虚拟机规范中没有对本地方法栈作强制规定,虚拟机可以自由实现,所以可以不是字节码。如果是以字节码实现的话,虚拟机栈本地方法栈就可以合二为一,事实上,OpenJDK和SunJDK所自带的HotSpot虚拟机就是直接将虚拟机栈和本地方法栈合二为一的。

Java虚拟机规范规定该区域也可抛出StackOverFlowError和OutOfMemoryError。

4、Java 堆

这个区域用来放置所有对象实例以及数组。不过在JIT(Just-in-time)情况下有些时候也有可能在栈上分配对象实例。堆也是java垃圾收集器管理的主要区域(所以很多时候会称它为GC堆)。

从GC回收的角度看,由于现在GC基本都是采用的分代收集算法,所以堆内存结构还可以分块成:新生代和老年代;再细一点的有Eden空间、From Survivor空间、To Survivor空间等。如下图:

 

 

 

 


5、方法区

方法区是可供各条线程共享的运行时内存区域。存储了每一个类的结构信息,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法

方法区创建时机:在虚拟机启动的时候创建。

方法区的容量:可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。方法区在实际内存空间中可以是不连续的。

见《JVM体系结构之三:方法区之1》和《JVM体系结构之三:方法区之2:常量池》

6、直接内存

直接内存(Direct Memory)虽然不是程序运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但这部分内存也被频繁使用,而且它也可能导致OutOfMemoryError异常出现。

在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native方法库直接分配堆外内存,然后通过一个存储在Java堆里面的DirecByteBuffer对象作为这块内存的引用进行操作。这样能在某些应用场景中显著提高性能,因为它避免了在Java堆和Native堆中来回复制数据。

显然,本机直接内存的分配不会受到Java堆大小的限制,但是,还是会受到本机总内存(包括RAM及SWAP区或者分页文件)的大小及处理器寻址空间的限制,从而导致动态扩展时出现OutOfMemoryError异常。

7、执行引擎

将字节码即时编译 优化 为本地代码, 然后执行。

在了解完这些知识以后,就可以知道:类和对象在运行时的内存里是怎么样的?以及各类型变量、方法在运行时是怎么交互的?

在程序运行时类是在方法区,实例对象本身在堆里面。

方法字节码在方法区。线程调用方法执行时创建栈帧并压栈,方法的参数和局部变量在栈帧的局部变量表。

对象的实例变量和对象一起在堆里,所以各个线程都可以共享访问对象的实例变量。

静态变量在方法区,所有对象共享。字符串常量等常量在运行时常量池。

各线程调用的方法,通过堆内的对象,方法区的静态数据,可以共享交互信息。

各线程调用的方法所有参数传递、方法返回值的返回,都是使用栈帧里的操作数栈来完成的。


5、方法区

方法区是可供各条线程共享的运行时内存区域。存储了每一个类的结构信息,例如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法

方法区创建时机:在虚拟机启动的时候创建。

方法区的容量:可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩。方法区在实际内存空间中可以是不连续的。

见《JVM体系结构之三:方法区之1》和《JVM体系结构之三:方法区之2:常量池》

6、直接内存

直接内存(Direct Memory)虽然不是程序运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域,但这部分内存也被频繁使用,而且它也可能导致OutOfMemoryError异常出现。

在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native方法库直接分配堆外内存,然后通过一个存储在Java堆里面的DirecByteBuffer对象作为这块内存的引用进行操作。这样能在某些应用场景中显著提高性能,因为它避免了在Java堆和Native堆中来回复制数据。

显然,本机直接内存的分配不会受到Java堆大小的限制,但是,还是会受到本机总内存(包括RAM及SWAP区或者分页文件)的大小及处理器寻址空间的限制,从而导致动态扩展时出现OutOfMemoryError异常。

7、执行引擎

将字节码即时编译 优化 为本地代码, 然后执行。

在了解完这些知识以后,就可以知道:类和对象在运行时的内存里是怎么样的?以及各类型变量、方法在运行时是怎么交互的?

在程序运行时类是在方法区,实例对象本身在堆里面。

方法字节码在方法区。线程调用方法执行时创建栈帧并压栈,方法的参数和局部变量在栈帧的局部变量表。

对象的实例变量和对象一起在堆里,所以各个线程都可以共享访问对象的实例变量。

静态变量在方法区,所有对象共享。字符串常量等常量在运行时常量池。

各线程调用的方法,通过堆内的对象,方法区的静态数据,可以共享交互信息。

各线程调用的方法所有参数传递、方法返回值的返回,都是使用栈帧里的操作数栈来完成的。

 

https://www.cnblogs.com/duanxz/p/3732300.html

转载于:https://www.cnblogs.com/chuancheng/p/11437715.html


http://www.niftyadmin.cn/n/3458654.html

相关文章

【转】协同开发中SVN使用规范试用

转自:http://www.cnblogs.com/BraveCheng/archive/2012/07/02/2573617.html 协同开发中SVN使用规范试用 目标,要求 本次svn提交规范主要针对当前项目中出现的svn管理难,开发流程控制难掌控,项目进度记录不准确等问题而提出。要求每…

学无止境·MySQL(3-2)

单表查询试题 单表题目一1、创建表2、查询出部门编号为30的所有员工3、所有销售员的姓名、编号和部门编号4、找出奖金高于工资的员工5、找出奖金高于工资60%的员工。6、 找出部门编号为10中所有经理,和部门编号为20中所有销售员的详细资料。7、找出部门编号为10中所…

爬虫-第六篇-scrapy图片爬取,请求传参,中间件,提升爬取效率

补充: 自动请求start_urls列表路径其实是执行了父类中的start_requests方法,默认为GET请求,如果想要发送POST请求,改写此方法即可. def start_requests(self):for url in self.start_urls:yield scrapy.Request(url,callbackself.parse) # LOG_FILE ./log.txt 日志文件输出,默…

小米成立AIoT战略委员会,加速落地All in AIoT战略 ...

雷锋网(公众号:雷锋网)3月7日消息,今天下午,小米集团组织部再次发布任命文件,宣布成立AIoT战略委员会。AIoT战略委员会隶属于集团技术委员会,负责促进AIoT相关业务和技术部门的协同,推动战略落地执行。 文…

二层交换

交换网络基础 交换机工作在数据链路层 ,通过MAC 地址转发数据帧 交换机在接受到一个主机的广播后,会以广播的形式从其他接口发送出去,这个过程叫做泛洪。 交换机在从广播中学习的 mac地址与对应的链接接口,写入mac表中 dis mac-a…

Spring Boot 2.2 首个里程碑版本 M1 发布

Spring Boot 2.2 首个里程碑版本 M1 已于昨天发布,可从里程碑仓库获取。官方表示该版本关闭了 140 多个 issue 和 PR。 有以下值得关注的更新: 将依赖项 Spring Data Moore 升级至 M2 版本提高配置属性数量较多时的绑定速度对 bean 进行延迟初始化的可选…

初始django

Web框架本质 https://www.cnblogs.com/liwenzhou/p/8258992.html 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。 import socket sk socket.socket() sk.bind((&q…

WiFi共享命令行

通过WiFi共享命令行程序可以轻松现在无线网络共享设置,彻底解决了手动设置网络共享的问题。 下载设置网络共享的命令行程序下载链接:http://down.51cto.com/data/2459318提取码:aaur 一、开启WiFi共享1、开启网络承载netsh wlan set hostedn…