聊下JVM内存模型

转载自 聊下JVM内存模型

 

1. JVM内存模型

 

 

2. 程序计数器(PC)

 

每个线程都会有自己私有的程序计数器(PC)。可以看作是当前线程所执行的字节码的行号指示器。
也可以理解为下一条将要执行的指令的地址或者行号。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、 循环、 跳转、 异常处理、 线程上下文切换,线程恢复时,都要依赖PC.

  • 如果线程正在执行的是一个Java方法,PC值为正在执行的虚拟机字节码指令的地址

  • 如果线程正在执行的是Native方法,PC值为空(未定义)

 

3.虚拟机栈(VM Stack)

 

VM Stack也是线程私有的区域。他是java方法执行时的字典:它里面记录了局部变量表、 操作数栈、 动态链接、 方法出口等信息。

在《java虚拟机规范》一书中对这部分的描述如下:

栈帧( Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。
栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。
栈帧的存储空间分配在 Java 虚拟机栈( §2.5.5)之中,每一个栈帧都有自己的局部变量表( Local Variables, §2.6.1)、操作数栈( OperandStack, §2.6.2)和指向当前方法所属的类的运行时常量池( §2.5.5)的引用。

说白了,VM Stack是一个,也是一块内存区域
所以,他是有大小的。虽然有大小,但是一般而言,各种虚拟机的实现都支持动态扩展这部分内存。

  • 如果线程请求的栈深度太大,则抛出StackOverflowError

  • 如果动态扩展时没有足够的大小,则抛出OutOfMemoryError

 

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

Java 虚拟机实现可能会使用到传统的栈(通常称之为“ C Stacks”)来支持 native 方法( 指使用 Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈( Native MethodStack)。

VM Stack是为执行java方法服务的,此处的Native Method Stack是为执行本地方法服务的。
此处的本地方法指定是和具体的底层操作系统层面相关的接口调用了(这部分太高高级了,不想深究……)。

《java虚拟机规范》中没有对这部分做具体的规定。所以就由VM的实现者自由发挥了。
有的虚拟机(比如HotSpot)将VM Stack和Native Method Stack合二为一,所以VM的另一种内存区域图就如下面所示了:

 

5.Java堆(Heap)

在 Java 虚拟机中,堆( Heap)是可供各条线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。

以下是本人对《java虚拟机规范》一书中对Java堆的介绍的总结:

  • 在虚拟机启动的时候就被创建

  • 是所有线程共享的内存区域

  • 存储了被自动内存管理系统所管理的各种对象

    • 这些受管理的对象无需,也无法显式地被销毁

    • 自动内存管理系统:Automatic StorageManagement System,也即是常说的”Garbage Collector(垃圾收集器)”

    • 并未指明用什么具体的技术去实现自动内存管理系统

  • Java 堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩

  • Java 堆所使用的内存不需要保证是连续的

  • 如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那 Java 虚拟机将会抛出一个OutOfMemoryError 异常

  • 实现者应当提供给程序员或者最终用户调节 Java 堆初始容量的手段

    • 对于可以动态扩展和收缩 Java 堆来说,则应当提供调节其最大、最小容量的手段

  • 所有的对象实例以及数组都要在堆上分配

 

6.方法区(Method Area)

 

方法区是由所有线程共享的内存区域。
方法区存储的大致内容如下:

  • 每一个类的结构信息

    • 运行时常量池( Runtime Constant Pool)

    • 字段和方法数据

    • 构造函数和普通方法的字节码内容

  • 类、实例、接口初始化时用到的特殊方法

每一个运行时常量池都分配在 Java 虚拟机的方法区之中,在类和接口被加载到虚拟机后,对应的运行时常量池就被创建出来。

  • 当创建类或接口的时候,如果构造运行时常量池所需要的内存空间超过了方法区所能提供的最大值,那 Java 虚拟机将会抛出一个 OutOfMemoryError 异常。

     

7.直接内存(Direct Memory)

 

此处的直接内存并不是由JVM管理的内存。他是利用本地方法库直接在java堆之外申请的内存区域。
比如NIO中的DirectByteBuffer就是操作直接内存的。

直接内存的好处就是避免了在java堆和native堆直接同步数据的步骤。但是他并不是由JVM来管理的。

 

 

1. JVM内存模型

 

 

2. 程序计数器(PC)

 

每个线程都会有自己私有的程序计数器(PC)。可以看作是当前线程所执行的字节码的行号指示器。
也可以理解为下一条将要执行的指令的地址或者行号。字节码解释器就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、 循环、 跳转、 异常处理、 线程上下文切换,线程恢复时,都要依赖PC.

  • 如果线程正在执行的是一个Java方法,PC值为正在执行的虚拟机字节码指令的地址

  • 如果线程正在执行的是Native方法,PC值为空(未定义)

 

3.虚拟机栈(VM Stack)

 

VM Stack也是线程私有的区域。他是java方法执行时的字典:它里面记录了局部变量表、 操作数栈、 动态链接、 方法出口等信息。

在《java虚拟机规范》一书中对这部分的描述如下:

栈帧( Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。
栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。
栈帧的存储空间分配在 Java 虚拟机栈( §2.5.5)之中,每一个栈帧都有自己的局部变量表( Local Variables, §2.6.1)、操作数栈( OperandStack, §2.6.2)和指向当前方法所属的类的运行时常量池( §2.5.5)的引用。

说白了,VM Stack是一个,也是一块内存区域
所以,他是有大小的。虽然有大小,但是一般而言,各种虚拟机的实现都支持动态扩展这部分内存。

  • 如果线程请求的栈深度太大,则抛出StackOverflowError

  • 如果动态扩展时没有足够的大小,则抛出OutOfMemoryError

 

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

Java 虚拟机实现可能会使用到传统的栈(通常称之为“ C Stacks”)来支持 native 方法( 指使用 Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈( Native MethodStack)。

VM Stack是为执行java方法服务的,此处的Native Method Stack是为执行本地方法服务的。
此处的本地方法指定是和具体的底层操作系统层面相关的接口调用了(这部分太高高级了,不想深究……)。

《java虚拟机规范》中没有对这部分做具体的规定。所以就由VM的实现者自由发挥了。
有的虚拟机(比如HotSpot)将VM Stack和Native Method Stack合二为一,所以VM的另一种内存区域图就如下面所示了:

 

5.Java堆(Heap)

在 Java 虚拟机中,堆( Heap)是可供各条线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。

以下是本人对《java虚拟机规范》一书中对Java堆的介绍的总结:

  • 在虚拟机启动的时候就被创建

  • 是所有线程共享的内存区域

  • 存储了被自动内存管理系统所管理的各种对象

    • 这些受管理的对象无需,也无法显式地被销毁

    • 自动内存管理系统:Automatic StorageManagement System,也即是常说的”Garbage Collector(垃圾收集器)”

    • 并未指明用什么具体的技术去实现自动内存管理系统

  • Java 堆的容量可以是固定大小的,也可以随着程序执行的需求动态扩展,并在不需要过多空间时自动收缩

  • Java 堆所使用的内存不需要保证是连续的

  • 如果实际所需的堆超过了自动内存管理系统能提供的最大容量,那 Java 虚拟机将会抛出一个OutOfMemoryError 异常

  • 实现者应当提供给程序员或者最终用户调节 Java 堆初始容量的手段

    • 对于可以动态扩展和收缩 Java 堆来说,则应当提供调节其最大、最小容量的手段

  • 所有的对象实例以及数组都要在堆上分配

 

6.方法区(Method Area)

 

方法区是由所有线程共享的内存区域。
方法区存储的大致内容如下:

  • 每一个类的结构信息

    • 运行时常量池( Runtime Constant Pool)

    • 字段和方法数据

    • 构造函数和普通方法的字节码内容

  • 类、实例、接口初始化时用到的特殊方法

每一个运行时常量池都分配在 Java 虚拟机的方法区之中,在类和接口被加载到虚拟机后,对应的运行时常量池就被创建出来。

  • 当创建类或接口的时候,如果构造运行时常量池所需要的内存空间超过了方法区所能提供的最大值,那 Java 虚拟机将会抛出一个 OutOfMemoryError 异常。

     

7.直接内存(Direct Memory)

 

此处的直接内存并不是由JVM管理的内存。他是利用本地方法库直接在java堆之外申请的内存区域。
比如NIO中的DirectByteBuffer就是操作直接内存的。

直接内存的好处就是避免了在java堆和native堆直接同步数据的步骤。但是他并不是由JVM来管理的。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/327164.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

泛型集合

作用 它是一个泛型类,而之前使用的时候并没有传递,说明java语法是允许的,这个时候传递的类型是Object类,虽然它是所有类的父类,可以存储任意的类型,但是在遍历、获取元素时需要原来的类型就要进行强制转换。…

ASP.NET Core + Angular 2 Template for Visual Studio

多个月以来,我和多个Github上的社区贡献者一起建立支持库、包,我们最终的目的是希望完成这样一个作为起点的模板,也就是基于把Typescript代码和Angular2宿主在ASP.NET Core项目中,这个模板包含一下这些方面: 服务端预加…

MyBatis中if - else if - else 的使用

http://www.leftso.com/blog/765.html 不过有他的替代 choose,写法如下&#xff1a; <choose><when test"params!null">right JOIN</when><otherwise>LEFT JOIN</otherwise></choose> 复制 <choose><when test…

Servlet使用适配器模式进行增删改查案例(Emp.java)

package org.entity;/*** * * 项目名称&#xff1a;test_BaseDao * 类名称&#xff1a;Emp * 类描述&#xff1a; 员工实体类 * 创建人&#xff1a;Mu Xiongxiong * 创建时间&#xff1a;2017-9-13 上午8:45:47 * 修改人&#xff1a;Mu Xiongxiong * 修改…

java发送http的get、post请求

转载自 java发送http的get、post请求 Http请求类 package wzh.Http;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.Li…

C#高性能TCP服务的多种实现方式

☆ 哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣&#xff0c;为了吸引眼球所以标题中一定要突出&#xff0c;其实我更喜欢的标题是《猴赛雷&#xff0c;C#编写TCP服务的花样姿势&#xff01;》。 本篇文章的主旨是使用 .NET/C# 实现 TCP 高性能服务的不同方式&a…

mysql中 where in 用法详解

https://blog.csdn.net/haibo0668/article/details/52584307 sssss mysql中 where in 用法详解 我是高手高手高高手 2016-09-19 11:33:29 102915 收藏 14 分类专栏&#xff1a; php MY SQL &#xfeff;&#xfeff; 这里分两种情况来介绍 WHERE column IN (value1,valu…

Servlet使用适配器模式进行增删改查案例(Dept.java)

package org.entity;/*** * * 项目名称&#xff1a;test_BaseDao * 类名称&#xff1a;Dept * 类描述&#xff1a; 部门表的实体类 * 创建人&#xff1a;Mu Xiongxiong * 创建时间&#xff1a;2017-9-13 上午8:44:37 * 修改人&#xff1a;Mu Xiongxiong *…

HashSet的存储方式

存储结构 存储过程

使用org.apache.commons.io.FileUtils,IOUtils工具类操作文件

转载自 使用org.apache.commons.io.FileUtils,IOUtils;工具类操作文件 File src new File("G:/2012/portal/login.jsp"); File tar new File("G:/2012/portal/loginZs.jsp"); File tarDir new File("G:/2012/portal/center/"); FileUti…

写给新手的WebAPI实践

此篇是写给新手的Demo&#xff0c;用于参考和借鉴&#xff0c;用于发散思路。老鸟可以忽略了。 自己经常有这种情况&#xff0c;遇到一个新东西或难题&#xff0c;在了解和解决之前总是说“等搞定了一定要写篇文章记录下来”&#xff0c;但是当掌握了之后&#xff0c;就感觉好简…

用limit 实现java的简单分页

https://blog.csdn.net/xinyuezitang/article/details/84324359 用limit 实现java的简单分页 xinyuezitang 2018-11-21 16:01:13 4447 收藏 9 分类专栏&#xff1a; Java 小Demo 文章标签&#xff1a; 分页 limit mysql 实现java分页 版权 一 mysql 中limit 用法 select …

Map集合的遍历

COPY/*** Map接口的使用* 特点&#xff1a;1.存储键值对 2.键不能重复&#xff0c;值可以重复 3.无序*/ public class Demo1 {public static void main(String[] args) {Map<String,Integer> mapnew HashMap<String, Integer>();//1.添加元素map.put("tang&qu…

Servlet使用适配器模式进行增删改查案例(IBaseDaoUtil.java)

/*** */ package org.dao;import java.util.List;/*** * * 项目名称&#xff1a;test_BaseDao * 类名称&#xff1a;IBaseDaoUtil * 类描述&#xff1a; 公共接口 * 创建人&#xff1a;Mu Xiongxiong * 创建时间&#xff1a;2017-9-10 上午11:02:57 * 修改人…

Mybatis使用IN语句查询

https://blog.csdn.net/u011781521/article/details/79669180 Mybatis使用IN语句查询 lfendo 2018-03-23 16:45:03 201525 收藏 140 分类专栏&#xff1a; MyBatis 文章标签&#xff1a; mybatis JAVA sql 版权 一、简介 在SQL语法中如果我们想使用in的话直接可以像如下一…

IdentityServer4 实现 OpenID Connect 和 OAuth 2.0

关于 OAuth 2.0 的相关内容&#xff0c;点击查看&#xff1a;ASP.NET WebApi OWIN 实现 OAuth 2.0 OpenID 是一个去中心化的网上身份认证系统。对于支持 OpenID 的网站&#xff0c;用户不需要记住像用户名和密码这样的传统验证标记。取而代之的是&#xff0c;他们只需要预先在一…

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

转载自 Java动态代理机制详解&#xff08;JDK 和CGLIB&#xff0c;Javassist&#xff0c;ASM&#xff09; class文件简介及加载 Java编译器编译好Java文件之后&#xff0c;产生.class 文件在磁盘中。这种class文件是二进制文件&#xff0c;内容是只有JVM虚拟机能够识别的机器码…

Servlet使用适配器模式进行增删改查案例(IDeptDao.java和IEmpDao.java)

这两个接口进行放置emp和dept单独接口 /*** */ package org.dao;import org.entity.Dept;/*** * * 项目名称&#xff1a;test_BaseDao * 类名称&#xff1a;IDeptDao * 类描述&#xff1a; 部门的私有接口&#xff0c;此接口专属于部门独立的功能公共的都在IBaseDaoUt…

彻底理解JAVA动态代理

转载自 彻底理解JAVA动态代理 代理设计模式 定义&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 代理模式的结构如下图所示。 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念。 代理模式示例代码 public interface Subject { pu…