java运行时数据区(pc寄存器、虚拟机栈(栈帧)、本地方法栈、java堆、方法区、运行时常量池、直接内存)

标签: jvm  java    jdk

2.1 概述

在这里插入图片描述


2.2.1 pc寄存器(程序计数器)

程序计数器是一块较小的内存空间,线程私有。它可以看作是当前线程所执行的字节码的行号指示器

字节码指令集,由操作码和操作数组成,.java文件编译后的.class就是操作数和操作码的集合。     .class文件的行号,记住指令运行到哪了;

每一条java虚拟机线程都有自己的pc寄存器,任何时刻,一个Java线程只会执行一个方法(该线程的当前方法)的代码;
    如果该方法是nativa,那么pc寄存器得值是undefined,如果不是native的,那么pc寄存器就保存jvm正在执行的字节码指令地址;
    程序计数器是唯一一块Java虚拟机规范中没有任何规定的OutOfMemoryError情况的区域;


2.2.2 Java虚拟机栈

用于存储栈帧


栈帧

用于存储局部变量表,操作数栈,动态链接,方法出口等信息;

https://blog.csdn.net/a616413086/article/details/51272309

每一个方法从被调用到执行完毕,都对应者一个栈帧在虚拟机栈中入栈到出栈的过程。


1 局部变量表

每个栈帧都包含一组变量列表,称之为局部变量表,用于存储 方法的形参方法内部定义的变量(局部变量)(这些变量也包括引用类型),和returnAddress(返回地址类型);
    局部变量表是编译期可知
    注意,引用类型的局部变量也会存储在局部变量表中,只不过存储的是引用类型的地址。

jvm使用局部变量表完成方法调用时方法的传递。通过索引来访问,第0个局部变量一定用来存储该实例方法所在对象的引用(this),static修饰的方法除外;

系统不会为局部变量赋予初始值(但是实例变量和类变量都会被赋予初始值)。也就是说局部变量表不存在类变量那样的准备阶段。


Solt

局部变量表的容量以变量槽(Slot)为最小单位,其中64位的double和long占用2个连续的solt,访问时访问索引小的solt,
    对于byte、short以及char类型的值在局部变量表之前,会被转换为int。
    因为方法的参数和局部变量,在编译器就已经确定了,所以局部变量表的空间大小在编译器就已经确定。


2 操作数栈

是用来描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧。

void spin(){
    int i ;
    for (i = 0;i<100;i++){
        ....
    } 
}

这个方法中, 0,100两个常量存放在操作数栈 整形变量i存放在局部变量变量表中

是一个后入先出栈(LIFO)。同局部变量表一样,操作数栈的最大深度也在编译的时候写入到方法的Code属性的max_stacks数据项中。

虚拟机在操作数栈中存储数据的方式和在局部变量区中是一样的,对于byte、short以及char类型的值在压入到操作数栈之前,也会被转换为int。

所有的操作码都是对操作数栈上的数据进行操作,对于每一个方法的调用,JVM会建立一个操作数栈,以供计算使用。和局部变量一样。操作数栈的最大深度也是编译的时候写入到方法表的code属性的max_stacks数据项中。
    另外,在概念模型中,两个栈帧作为虚拟机栈的元素,相互之间是完全独立的,但是大多数虚拟机的实现里都会作一些优化处理,令两个栈帧出现一部分重叠。

3 动态链接

一个引用,(当前方法所在类型的)运行时常量池的引用

https://zhuanlan.zhihu.com/p/45354152

在一个class文件中,一个方法要调用其他方法,需要将这些方法的符号引用转化为其在内存地址中的直接引用,而符号引用存在于方法区中的运行时常量池。
    Java虚拟机栈中,每个栈帧都包含一个指向运行时常量池中该栈所属方法的符号引用,持有这个引用的目的是为了支持方法调用过程中的动态链接(Dynamic Linking)
    这些符号引用一部分会在类加载阶段或者第一次使用时就直接转化为直接引用,这类转化称为静态解析。另一部分将在每次运行期间转化为直接引用,这类转化称为动态连接。在一个class文件中,一个方法要调用其他方法,需要将这些方法的符号引用转化为其在内存地址中的直接引用,而符号引用存在于方法区中的运行时常量池。


2.2.3 本地方法栈

与Java虚拟机栈类似,用来支持native方法(除java语言外的语言编写的方法)的栈,与之对应的虚拟机栈是为java方法(字节码)服务


2.2.4 Java堆

用于存放对象实例。(几乎所有的对象实例以及数组都在这里存放)
在这里插入图片描述

JVM管理的内存中最大的一块。
分为新生代和老年代,新生代再细分有Edon,Form Suivivor,To Suivivor等。
线程共享的Java堆可能划分出多个线程私有的分配缓冲区(TLAB)。
Java堆 物理上不连续,逻辑连续。


2.2.5 方法区

JDK7 之前用于存储已被虚拟机加载的类信息、常量、字符串常量、类静态变量、即时编译器编译后的代码等数据。

  • 也被称为永久代(被称为永久代HotSpot设计团队希望将GC分带手机扩展到方法区)
  • 线程共享
  • 会抛出 OutOfMemoryError 异常

执行过程 eg

cn.test.MainDemo{
main方法{
A a = new A()
}
}

先 javac +类名进行编译,然后java+类名运行,此时加载cn.test.MainDemo到方法区,main方法入栈,遇到new A()时(遇到A a时,并不加载A的代码到方法区,只有创建对象时(new)才加载)A的构造器入栈


2.2.6 运行时常量池

用于存放编译期生成的各种字面量和符号引用

  • 是方法区的一部分。
  • Class文件中除了有类的版本/字段/方法/接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将类在加载后进入方法区的运行时常量池中存放。运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多的是 String.intern()方法
  • 受方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 异常。

在这里插入图片描述

存储(方法或者类的)变量字面量(编译时能知道)和运行时解析才知道的方法或者字段引用, 在方法区分配

在目前已经发布的JDK1.7的HotSpot中,已经把原来存放在方法区中的字符串常量池移出。根据查阅的资料显示在JDK1.7以后的版本中字符串常量池移到堆内存区域


2.2.7 直接内存

直接内存不是jvm运行时数据区的一部分,也不是jvm规范中定义的内存区域,

  • 直接内存也被频繁使用,也会出现OOM异常。

的HotSpot中,已经把原来存放在方法区中的字符串常量池移出。根据查阅的资料显示在JDK1.7以后的版本中字符串常量池移到堆内存区域


2.2.7 直接内存

直接内存不是jvm运行时数据区的一部分,也不是jvm规范中定义的内存区域,

  • 直接内存也被频繁使用,也会出现OOM异常。

版权声明:本文为qq_43369986原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_43369986/article/details/108996832

智能推荐

Hibernate学习总结(一)

一、Hibernate简介 一个持久层的ORM框架。ORM:Object Relational Mapping(对象关系映射)。指的是将一个Java中的对象与关系型数据库中的表建立一种映射关系,从而操作对象就可以操作数据库中的表。 二、Hibernate入门 1、创建一个项目,引入jar包 hibernate用到的jar包 2、创建表 3、创建实体类 4、创建映射(*****) 映射需要通过XML...

Linux系统NFS

文章目录 1. nfs简介 1.1 nfs特点 1.2 使用nfs的好处 1.3 nfs的体系组成 1.4 nfs的应用场景 2. nfs工作机制 2.1 RPC 2.2 NIS 2.3 nfs工作机制 3. exports文件的格式 4. nfs管理 5. 作业 5.1手动搭建一个nfs服务器 5.1.1开放/nfs/shared目录,供所有用户查阅资料 5.1.2 开放/nfs/upload目...

关于java中String,StringBuffer,StringBuilder的区别以及StringBuffer,StringBuilder的安全性问题

这里的结果就是正确的然后我们来看他的append方法 它在前边加了一个synchronized来修饰,相当于同时只能有一个线程来访问他,这样就不会产生上边的问题但同时他的效率也就比StringBuilder低,...

Django连接现有mysql数据库

1、打开cmd后cd到项目位置 2、建立项目 django-admin startproject test2 3、编辑项目中的配置文件, mysite/settings.py ,告诉Django你的数据库连接参数和数据库名。具体的说,要提供 DATABASE_NAME , DATABASE_ENGINE , DATAB...

ShareSDK新浪微博登录时报错error:redirect_uri_mismatch

今天用 ShareSDK 做第三方登录的时候碰到个问题,明明在微博平台的应用审核已经通过了,但是调用登录接口的时候一直报错,错误如下: 出现这个错误是因为在微博开放平台上没有设置回调地址,或者设置的回调地址与本地XML中的地址不一致。 在sharesdk.xml文件当中对于微博的设置: 其中RedirectUrl为设置的回调地址,这里的地址必须要与微博开发平台设置的地址相同,否则就会出现上面的错误...

猜你喜欢

python解析网络封包方法

2019独角兽企业重金招聘Python工程师标准>>> 在使用Python解析网络数据包时,使用网络字节序解析,参见下表。 C语言的数据类型和Python的数据类型对照表请参见下表。 接下来对封包与解包进行举例说明。 version type id content unsigned short unsigned short unsigned int unsigned int 封包...

python3:时间方法,异常处理,系统文件相关模块(os)

文章目录 时间方法 time模块 时间表示方法: time模块的方法 datetime模块 异常处理 触发异常 创建mydiv.py脚本,要求如下: 创建myerror.py脚本,要求如下: os模块 实现ls -R(os.walk) os.path pickle模块 记账脚本 时间方法 time模块 时间表示方法: 时间戳:自1970-1-1 0:00:00到某一时间点之间的秒数 UTC时间:世...

负载均衡群集——LVS+DR模型

一、实验组成 调度器 192.168.100:41 web1 192.168.100:42 web2 192.168.100.43 NFS共享服务器 192.168.100.44 二、实验拓扑 三、实验配置 3.1在调度器配置:192.168.100.41 配置虚拟IP地址(VIP) 调整/proc响应参数 对于 DR 群集模式来说,由于 LVS 负载调度器和各节点需要共用 VIP 地址,应该关闭...

adb无线连接时appium找不到设备

问题描述 以前使用USB连接真机,运行appium时一直正常,连接参数如下: 最近为了方便,使用adb无线连接真机,adb版本为1.0.40,真机安卓版本10,连接后,通过adb devices能够查看到连接的设备: adb无线连接是正常的,但每次运行时appium都找不到无线连接的设备,陷入重启adb循环: 解决流程 1.因为是没找到设备,所以在appium连接参数中增加了"udid&...

Mybatis_CRUD(基于xml的增删改查操作)

dao IUserDao domain User QueryVo SqlMapConfig.xml com.itheima.dao IUserDao.xml com.itheima.test 执行原理图:...