Java 虚拟机-Java内存区域

简要介绍Java的内存区域:

  • 运行时数据区域
  • HotSpot虚拟机对象

一、概览

二、运行时数据区域

2.1 程序计数器

Program Counter Register,代表当前线程所执行的字节码的行号指示器,操作系统中的PC,这两个是一个概念。执行时就是通过改变这个计数器来选取下一条需要执行的字节码指令。Java支持多线程,所以每个线程有自己独享的PC,类似于操作系统线程表中的一个属性。

2.2 Java虚拟机栈

和PC一样,是线程私有的,和线程的生命周期一样。虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行的时候都会创建一个栈桢(Stack frame),用与存储局部变量,操作数、动态链接、方法出口等信息。局部变量放在栈中的局部变量表中,该表中存放了编译器可知的基本数据类型(int。float,string。。)和对象的引用(reference)。

2.3 本地方法栈

Native Method Stack与Java虚拟机栈的作用非常相似,不过用于为虚拟机调用到的Native方法服务。

2.4 Java堆

Java堆被所有线程所共享,是Java程序的内存,在虚拟机启动时创建,该内存区域的目的就是存放对象实例。Java堆是垃圾回收器(GC)管理的主要区域。

2.5 方法区

Method Area各个线程共享的区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,

方法区内有一块特殊的区域叫运行时常量池(Runtime Constant Pool),用于存放编译时生成的各种字面量和符号引用(字符串)

2.6 直接内存

直接内存不是虚拟机运行时的一部分,但是会影响到Java堆的大小

三、HOTSPOT中虚拟机对象

3.1 对象的创建

Java是一门面向对象语言,对象的创建是通过new关键字来完成的。主要步骤:

  1. 先去方法区检查类是否被加载
  2. 没有加载则先加载类到方法区
  3. 为对象分配内存(类被加载后所需要的空间是已知的)
  4. 分配内存并发控制(仿制同一块内存被分配给多个对象)
  5. 将所分配的内存空间初始化为0
  6. 将对象的基本信息(属于那个类,对象哈希码,GC代领等)放在对象头中(Object Header)
  7. 至此新对象已经产生
  8. 调用Init方法,对对象的属性按照程序员的想法进行赋值

3.2 对象内存布局

对象在内存中主要分三块:

  1. 对象头(Header):第一部分存储对象自身的数据,如哈希码,GC代龄等,另外一部分是类型指针,虚拟机通过这个指针来确定这个对象是那个类的实例
  2. 实例数据(Instance Data):对象真正存储的有效信息,程序代码中定义的各种字段的内容,父类中定义的也会被继承下来。
  3. 对齐填充(Padding):没有特殊意义,占位符,对象的大小必须是8字节的整数倍。

3.3 对象的访问定位

建立对象是为了使用对象,java程序需要通过存储在栈上的reference数据来操作对上的具体对象,reference类型是一个指向对象的引用,并没有定义这个歌引用该通过何种方式去定位、访问堆中对象的具体位置,所以对象访问方式也是取决于虚拟机的实现方式而定,目前主流有两种:

  1. 使用句柄访问对象

  

  使用句柄的好处是句柄稳定,当对象被移动(GC后)时只改变句柄中的实例数据指针,而Reference本事不需要修改。

  2. 使用指针访问对象

  

  使用直接指针的最大好处就是速度更快,节省了一次指针定位的时间开销。

时间: 2024-10-15 08:41:20

Java 虚拟机-Java内存区域的相关文章

Java虚拟机各内存区域的位置及功能的介绍

Java虚拟机运行时数据区: 相关区域介绍: 程序计数器: 功能:当前线程所执行字节码的行号指示器.若是Java方法记录指令地址,若为Native方法,则不记录 隔离性:线程隔离 Error:无 Java虚拟机栈: 功能:描述Java方法执行的内存模型:每个方法执行的同时都会创建一个栈帧,用于存储局部变量表.操作数栈.动态链接.方法出口等信息. 隔离性:线程隔离 Error:线程请求的栈深度大于虚拟机所允许的深度时,抛出 StackOverflowError 异常: 动态扩展时无法申请到足够的内

深入理解Java虚拟机笔记---内存区域

Java虚拟机在执行Java程序过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域有自各的用途,以及创建及销毁时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁.根据<Java虚拟机规范(第2版)>规定,Java虚拟机管理的内存区域包括以下几个运行时数据区域,下如图 1.程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.字节码解释器工作时就是通过

java虚拟机01-java内存区域与内存溢出异常

1.运行时数据区域 1.程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行字节码的行号指示器,字节码解释器工作时就是通过改变程序计数器的值来选取下一条指令的地址.分支.循环.跳转.异常处理.线程恢复等基础功能都是由这个计数器来完成.    每一条线程都要有一个属于自己的独立的程序计数器,所以该块内存是线程私有的    如果当前执行的是一个java方法,则这个计数器记录的是正在执行指令的字节码地址:如果当前当前执行的是一个native方法,则计数器的值为空 (undefined)    

JAVA虚拟机JVM-1.内存区域

运行时数据区域 包含:程序计数器,java虚拟机栈,本地方法栈,java堆,方法区,运行时常量池.具体相关结构如下图. 区域 是否公用 相关概念 其他描述 程序计数器 线程私有 当前线程执行的字节码行号指示器 如果当前线程执行的java方法,那么计数器 java虚拟机栈 线程私有 java方法执行的线程内存模型 方法执行的时候创建的栈帧用户保存局部变量表,操作数栈,动态链接,方法出口等信息.可能抛出StackOutflowError异常. 本地方法栈 线程私有 本地方法执行的线程内存模型 本地N

Java虚拟机的内存区域

本博文只是源自周志明<深入理解Java虚拟机> Java运行数据区图解: 程序计数器图解: Java的虚拟机栈图解: Java的本地方法栈图解: Java堆图解: 直接内存图解:

深入理解java虚拟机一 JAVA运行时内存区域与class文件

一 JAVA运行时内存区域 JVM在加载class文件时,会将class文件定义的数据结构转为运行时内存中的数据,那么jvm是如何安排运行时的内存区域呢? jvm将运行时内存划分为以下几个部分: 堆:所有线程共享 方法区:类信息.静态变量.常量等 运行时常量池:class文件的常量池(字面常量和符号引用)+运行时产生的常量 程序计数器:  当前线程执行的字节码的行号指示器 虚拟机栈:栈帧 = 本地局部变量表.操作数栈.动态链接.出口信息 本地方法栈:native方法 直接内存:不属于jvm管理,

Java虚拟机的内存管理

众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作. 虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏. 反而,某程度上,当出现内存泄漏,Debug会变得难度更大. 所以,Java程序员,有必要去了解Java虚拟机对于内存的管理以及垃圾回收的机制. Java虚拟机是如何判断一个对象可以回收? 当一个对象没有被任何其他所引用时,这个对象被Java虚拟机视为可回收. 早起的虚拟机,使用引用计数的方法判断对象是否可回

Java虚拟机:内存模型详解

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实例的时候,虚拟机要为对象分配内存,Java虚拟机又是如何配分内存的呢?这些都涉及到Java虚拟机的内存划分机制,今天我们就来探究一下Java虚拟机的内存模型. Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途以及创建和销毁的时间,有的区域随

如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习<深入理解java虚拟机-JVM高级特性与最佳实践>这本书,终于初步了解了一下java虚拟机的内存模型.本文通过写出使jvm发生内存溢出异常的代码来对自己的学习结果进行总结,同时也提醒自己以后写代码时候不要再跳进这个坑啦. java的内存管理是由java虚拟机自动进行管理的,并不需要程序员过多的手动干预

Java虚拟机之内存简介

本文主要介绍Java虚拟机的内存分布以及对象的创建过程. 一.Java虚拟机的内存分布 文章开始前读者需要了解Java虚拟机的运行时数据区是怎样划分的.如下图所示: 1.程序计数器(Program Counter Register) 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器. 由于Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,所以在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令.因此,为