`
perfect5085
  • 浏览: 271155 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JVM运行时内存分配

 
阅读更多

Inside JVM运行时数据区 

============================================================================================

<一>:方法区: 

JVM中被装载的类型信息存储在一个逻辑上被称为方法区的内存中,

JVM在装载完CLASS文件后提取其中的类型信息并将之存储在方法区。

该类型的静态变量同样也存储在方法区中。由于所有的线程共享方法区,

所以对方法区数据的访问必须考虑到线程的同步。 

方法区的大小是不固定的,

JVM可以通过装载新类型或者卸载已有类型来动态的调整方法区的大小,

即可以改变方法区所占用的内存。

方法区不一定是连续的,方法区可以在一个堆中自由分配。 


JVM保存的在方法区中的存储类型以下信息:

基本信息:

1,此类型的全限定名 

2,此类型的直接超类的全限定名(除非这个类型为java.lang.object,它没有超类) 

3,此类型为接口还是类 

4,此类型的访问修饰符号(public,abstact或final的某个子集) 

具体信息 :

5,此类型的常量池 

6,字段信息 

7,方法信息 

8,除常量以外的所有静态变量 

9,一个到类classLoader的引用 

10,一个到Class类的引用 

===================================================

常量池:可以理解为本地指针数组,在JAVA的动态连接中起核心的左右,后边再做详细的介绍。 

为了尽可能的提高访问的效率,必须优化存储在方法区中的类型信息的数据结构。

所以,实现中还可以加如其他数据结构以加快访问原始数据的速度,

如方法表。JVM为每个装载的非抽象类,都生成一个方法表,把他作为类信息的一部分保存在方法区。

方法表也是一个本地指针数组,其元素为方法的入口地址。方法表所指向实例方法的数据包括以下信息: 

1,此方法的操作数栈和局部变量的大小 

2,此方法的字节码 

3,异常表 

===================================================

JVM可以为每个对象生成一份方法表的copy(这样比较耗内存,但能提高访问的速度)或只在对象里保存到方法区中方法表的引用。

这和C++中的VTBL很象,在C++中,对象有实例数据和一组指向对象可以调用的虚拟函数指针组成。 

============================================================================================

<二>:堆 

Java程序在运行时创建的所有类室例或数组都放在同一个堆中,而一个JVM实例只有一个堆空间,所有线程都共享这个堆。

堆空间可以自由的伸缩,也不必是连续的。 


常见的堆空间的设计: 

a.把堆空间分为两部分:句柄池和对象池,对象的引用为指向句柄池的本地指针,句柄池里的每个条目分为两部分,

一部分为指向对象池的本地指针,一部分为指向方法区类数据区的本地指针。

对象池里保存的是实例对象的数据,此数据是实例私有的。

好处:有利于内存碎片的整理,当移动对象池中的对象时,句柄部分只需要修改指向对象池条目的地址。

缺点:就是两级指针的访问。 

b.使对象指针直接的指向对象数据,该数据包括指向方法区方法区数据类类型的指针和对象的实例数据。

这样的优缺点正好和前边的方法相反。当移动堆中的对象时,对象的指针也得跟着改变,这就必须在整个运行时数据区中更新被移动对象的引用。 


以上两种方法的思想可以类比为对链表和数组的删除和加入操作。 


在Java中,数组和其他对象一样,总是存储在堆中并拥有一个与他们的类向关联的CLASS实例,

所有具有相同维度和类型的数组都是一个类的实例,而不管数组的长度。 

============================================================================================

<三>:程序记数器 

每个线程都有自己的程序记数器,它的内容总是下一条将被执行指令的地址。 

============================================================================================

<四>:Java栈 

当一个线程被创建时都将得到自己的程序记数器和Java栈,

Java栈以帧为单位保存调用信息。

当线程调用一个方法时,JVM会压如一新的栈帧到Java栈,反之则弹出。

也就是说,JVM只会对Java栈执行两种操作:以帧为单位的压栈和弹栈。

帧的大小根据调用信息是可变的,后边做详细的介绍。

由于Java栈上的数据是此线程私有的,因此不需考虑多线程下的栈数据的线程安全问题。 

================================================

Inside JVM栈帧由三部分组成:局部变量区,操作数栈和帧数据区。 

a.局部变量区 

局部变量区的大小由调用方法的参数和方法的局部变量所决定。

编译器按声名顺序将他们放到局部变量数组,此数组以字长为单位,从0开始记数。

如果是实例方法,数组的第一个元素为实例的this指针。 

在Java中,所有的对象都按引用传递,并且对象存储在堆中,在局部变量或操作数栈中不会有对象的COPY,只有对象引用。 

b.操作数栈 

操作数栈也是以字长为单位的数组,但不同于局部变量数组以索引去访问,

它是通过标准的栈操作,压栈和弹栈来访问的。

JVM没有寄存器,程序记数器也无法被程序指令直接访问。JVM的运行方式是基于栈的而非基于寄存器的,

JVM的指令是从操作数栈中而不是寄存器中取得操作数的。虽然指令也可以从其他地方取得操作数,

比如从字节码流中跟随在操作码之后的字节中或从常量池中,但主要还是从操作数栈中获取操作数。 

JVM把操作数栈作为它的工作区,大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈,

然后等相关的指令将结果再次弹出。操作数栈扮演了暂存操作数的角色。 

C.帧数据区 

除局部变量区和操作数栈外,Java栈帧还数据来支持常量池的解析、正常方法的返回以及异常派发机制。

这些信息都保存在Java栈帧的帧数据区中。JVM可以通过帧数据区中指向常量池的指针来执行某个需要用到常量池数据的指令。 

============================================================================================

<五>:本地方法栈 

当线程调用本地方法时,JVM会保持Java栈不变,不再在线程的Java栈中压入新的帧,Inside JVM只是简单地动态连接并直接调用本地方法。

但是,本地方法有可能回调JVM中的Java方法,此时该线程会保存本地方法栈的状态并进入Java栈,在Java栈压入新的栈帧。 

分享到:
评论

相关推荐

    JVM内存空间分配笔记

    ### JVM内存空间分配详解 #### 一、JVM内存模型概览 ...综上所述,理解JVM内存分配机制对于Java开发者来说至关重要,这不仅有助于编写高效、稳定的代码,还能在遇到性能瓶颈时快速定位问题并进行优化。

    搜索引擎创建索引时JVM 运行时内存溢出解决方案

    综上所述,解决JVM运行时内存溢出问题需要从多个角度进行:合理调整JVM内存参数、优化索引构建算法、监控系统状态并进行必要的硬件升级,甚至考虑采用分布式计算。只有这样,我们才能确保搜索引擎在创建索引时高效、...

    Sun JVM原理与内存管理

    ### Sun JVM原理与内存管理 #### 一、Sun JDK 1.6 GC (Garbage Collector) Sun JDK 1.6 的垃圾收集器(GC)是其内存管理的关键组成...通过合理的内存分配策略和恰当的 GC 调整,可以显著提高应用程序的性能和稳定性。

    Java运行时内存分配

    ### Java运行时内存分配详解 #### 一、引言 Java作为一种广泛使用的编程语言,其内存管理机制一直是开发者关注的重点之一。Java程序在运行时如何分配内存?对象是如何存储的?这些问题不仅对于深入理解Java虚拟机...

    java中jvm内存分配相关资料总结整理

    7. **JVM运行原理** - **类加载机制**:JVM通过类加载器加载类,包括加载、验证、准备、解析和初始化五个阶段。 - **字节码执行**:通过解释器或即时编译器(如HotSpot的C1、C2编译器)将字节码转化为机器码执行。...

    Jvm对象内存分配理解

    Jvm 对象内存分配理解 Jvm 对象内存分配是 Java 虚拟机(Jvm)中的一种机制,用于在堆中分配对象的内存空间。该机制涉及到类加载检查、内存分配、对象初始化等多个步骤。 类加载检查 在 Jvm 对象内存分配中,首先...

    JVM初始分配的内存.doc JVM初始分配的内存.doc

    - **定义**:指定了JVM运行过程中所能使用的最大堆内存大小。 - **默认值**:默认情况下,JVM的最大堆内存大小为物理内存的1/4。 - **意义**:通过限制最大堆内存大小,可以避免Java应用占用过多内存资源而导致...

    JVM内存分配与垃圾回收详解

    JVM 内存分配主要涉及到五个运行时数据区域:程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区。 1. 程序计数器:它是线程私有的,一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号...

    03-VIP-JVM内存分配机制与垃圾回收算法1

    Java虚拟机(JVM)内存分配机制和垃圾回收(Garbage Collection, GC)是Java编程中的核心概念,它们直接影响到程序的性能和稳定性。本文主要围绕JVM内存区域的分配策略,尤其是对象在新生代(Young Generation)的...

    JVM内存溢出问题解析

    堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,但缺点是要在运行时动态分配内存,存取速度较慢。 JVM 如何设置虚拟内存?在 JVM 中,如果 98%的时间是用于 GC 且可用的 Heap size 不足 2%的时候...

    jvm 内存分析文档

    JVM内存管理主要包括内存结构、内存分配以及垃圾回收(GC)等方面。了解这些知识对于优化Java应用程序的性能至关重要。 ### 1. JVM内存结构 #### 1.1.1 JVM内存概述 JVM内存分为几个关键区域,每个区域都有特定的...

    JVM+Java程序运行过程内存分配图解

    1、JVM 内存分配图解的 Visio 工程图。 2、直接下载使用、可自行调整和修改

    idea插件JVM内存工具JProfiler11

    1. **内存分配和泄漏检测**:JProfiler11能详细追踪对象的创建、存活和销毁过程,帮助识别内存泄漏。通过查看对象分配图表,可以发现哪些类或方法在消耗大量内存,从而定位潜在的问题。 2. **垃圾收集分析**:...

    Jvm内存分配(7)

    《Jvm内存分配(7)》这篇博文主要探讨的是Java虚拟机(JVM)中的内存管理,特别是关于内存分配的相关知识。在Java程序运行时,JVM会为不同部分的内存区域进行分配,以保证程序的正常执行。以下是对这一主题的详细...

    java虚拟机jvm及Tomcat中的jvm有关内存的设置与调优

    通过命令行参数,我们可以精细地控制JVM的内存分配,以适应不同的应用场景。以下是一些关键参数的解读与实践指南: 1. **-Xms**:设置JVM初始堆内存大小。保持-Xms和-Xmx相等,有助于减少GC停顿时间,尤其在Server...

    JVM-内存管理 2012-12.pdf

    内存分配指的是当应用程序创建对象时,JVM会为对象分配内存。这个过程对Java程序员来说是透明的,通常不需要干预。对象通常在Java堆的新生代的Eden区创建,当Eden区空间不足时,会触发一次Minor GC(年轻代垃圾收集...

    JVM的运行机制

    总结来说,JVM的运行机制是Java平台无关性的关键,它通过字节码和解释器实现了代码的跨平台执行,同时通过垃圾回收和内存管理提供了高效且安全的运行环境。理解JVM的工作原理对于优化Java应用性能、排查问题和开发...

    java获得jvm内存大小

    通过动态地调整`-Xms`和`-Xmx`参数,可以在运行时根据实际需求优化内存分配,从而提高程序的性能和稳定性。此外,定期检查和分析`heapSize`、`heapMaxSize`和`heapFreeSize`等指标,可以帮助开发者及时发现潜在的...

Global site tag (gtag.js) - Google Analytics