JVM内存划分总结

概述

在说jvm内存划分之前,先来说下java程序具体的执行流程:

Java源文件经过java编译器编译后变成class字节码文件,

Jvm的classloader加载class文件完成后,交由execution engine执行。

执行引擎执行过程中用到的所有数据和信息,都存储在runtime data area中。

Runtime data  area 就是我们常说的JVM内存。

Runtime data area

Runtime data area 都包括什么呢?

《Java虚拟机规范》中规定,运行时数据区,主要包含:本地方法栈(native method stack),java栈(VM stack),程序计数器(programs counter register),堆(heap),方法区(method area)。

《java虚拟机规范》虽然规定了虚拟机应该包含哪些部分,但是并没有具体的实现规定,所以不同的虚拟机会有不同的实现方式。

Runtime data area都存放哪些数据?

1,程序计数器

程序计数器:保存的是下一条执行命令的内存地址。

在得到指令地址后,程序计数器会自动指向下一条指令的内存地址。具体实现视不同是虚拟机而定,这里将的只是概念和程序计数器的作用。

在JVM中,多线程是轮流获取cpu执行权的,所以,每个线程都会有自己的程序计数器。并且他们不会互相干扰。

在JVM规范中,如果当前程序执行的是native方法,程序计数器中的值应该是下一条指令的地址,如果是非native方法,程序计数器中的值应该是undefined。

由于程序计数器中存储的数据占用的空间,不会随程序的执行发生改变,所以程序计数器不会发生内存溢出现象。

2,java栈

Java栈也叫虚拟机栈,也就是我们常说的栈,java栈是java方法执行的内存模型。

Java栈中存放的是一个个的栈帧,每个栈帧包括:局部变量表,操作数栈,运行时常量池的引用,方法返回地址,附加信息。

当线程调用一个方法的时候,就会创建一个栈帧,并且进行压栈操作。方法执行完毕后出栈。由此可知,线程当前执行的方法一定是在栈顶的。到这里大家应该明白了,为什么递归的时候,一个不注意就会栈溢出了。栈这部分空间对程序员而言是不透明的,完全由系统自动实施。

栈帧中的各部分都是什么呢?

局部变量表

局部变量表:存储方法中的局部变量,局部变量分基本数据类型和引用数据类型,

针对基本数据类型的变量,存储的是值(每种基本数据类型都有固定的内存占用大小),引用数据类型的变量存储的是对象的引用。局部变量表的大小,在编译器时期就可以确定,所以程序执行期间,局部变量表的大小是不会发生改变的。

操作数栈:线程执行方法的过程,实际上就是执行语句的过程,归根到底就是计算机计算的过程。然而程序中所有的计算都是借住于操作数栈来完成的。可以理解成,它就是用来做计算的。

运行时常量池的引用:方法执行过程中可能会用到类中的常量,必须要有一个引用指向运行时常量。

方法返回地址:方法执行完成后,要返回之前调用它的地方,因此栈帧中必须保存方法的返回地址。

附加信息:java虚拟机规范允许一些虚拟机的具体实现增加一些规范中没有描述的信息到栈帧中,例如与调试相关的信息,这部分信息完全取决于虚拟机的具体实现。

3,本地方法栈

本地方法栈和java栈的原理和作用是非常相似的。区别是值java栈是为执行java方法执行服务的。本地方法栈是执行为native方法服务的。JVM规范中并没有对本地方发展的具体实现和数据接口做强制规定,虚拟机的具体实现可以自由实现它。比如hotSopt虚拟机中的实现就是将本地方法栈和java栈合二为一。

4,堆

Java中的堆是用来存储对象本身和数组的(数组的指针在java栈中)。

堆这部分空间是java垃圾回收的主要区域。

堆是被所有线程共享的,在JVM中只有一个堆。

5,方法区

它和堆一样是所有线程共享的。

方法区中主要存储了每个类的信息(比如类的名称,方法信息,字段信息),静态变量,常量,编译器编码后的代码等等。

常量池中除了包含代码中所定义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值外,还包含一些以文本形式出现的符号引用(运行时常量池),比如:

  类和接口的全限定名;

  字段的名称和描述符;

  方法和名称和描述符。

补充:

在class文件中除了类的 字段,方法,接口等描述,还有一项信息是常量池,用来存储编译期间生成的字面量和符号引用。

时间: 2024-10-27 05:02:45

JVM内存划分总结的相关文章

JVM内存划分以及值传递和引用传递的区别

4-8-2017_SHJavaTraing_Day05 一.JVM对自己的内存划分为5个区域    1.方法栈:所有的方法运行的时候进入内存    2.堆:存储的是容器和对象    3.方法和数据共享: 运行时期class文件进入的地方    4.本地方法栈: JVM调用了系统中的功能    5.寄存器:内存和CUP之间 二.值传递和引用传递的区别(易错内容) 1.方法参数是基本数据类型 方法参数是基本数据类型时,传递的是值. 1 //演示方法参数是基本数据类型的传递 2 class Demo{

JVM内存区域划分总结

发现网上有两个版本的JVM内存划分,一个是按照<深入理解JVM虚拟机>上的版本,包含程序计数器等,按照是否线程共享划分. 另一个我觉得更好记一些,也更适合我自己,在这里记录一下. 首先上思维导图: 一个个来说道吧. 堆内存 heap 堆内存主要被划分为新生代和老年代(差不多的意思) 基本上所有对象实例都在堆中创建,因此堆内存经常发生GC回收操作.新的对象首先分配在Eden区,两个Surviior区仅作为Eden区的缓冲使用.每次GC回收一次,对象的age值就+1,当Survivor区对象age

JVM内存结构(运行时数据区)

前言 Java程序的运行是通过Java虚拟机来实现的.通过类加载器将class字节码文件加载进JVM,然后根据预定的规则执行.Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些内存区域被统一叫做运行时数据区.Java运行时数据区大致可以划分为5个部分.在这里要特别指出,我们现在说的JVM内存划分是概念模型.如下图所示: JVM运行时数据区分为5种: 程序计数器 虚拟机栈(java栈) 堆 方法区 本地方法栈 程序计数器 程序计数器是一块较小的内存空间,它可

jvm系列 (一) ---jvm内存区域与溢出

jvm内存区域与溢出 为什么学习jvm 木板原理,最短的一块板决定一个水的深度,当一个系统垃圾收集成为瓶颈的时候,那么就需要你对jvm的了解掌握. 当一个系统出现内存溢出,内存泄露的时候,因为你懂jvm知识,可以更加快速定位错误,可以通过参数去合理设置各内存区域的内存容量. 因为你对jvm的认识,写代码的时候会潜意识地让你注意代码质量,可能你会说是那是小小的性能提升,但是量变会导致质变的. jvm内存区域 jvm内存划分 方法区 虚拟机栈 本地方法栈 堆 程序计数器 程序计数器 当前线程所执行的

JVM内存管理&amp;GC

一.JVM内存划分 |--------------------|-------------PC寄存器-------| |----方法区 ---------|--------------java 虚拟机栈--| |----堆区----------- |-------------本地方法栈------| |----共享区域------- |--------------线程独有-------| 其中左边为共享内存空间,右边为线程独有的线程级别的内存 各个区存储什么? 1.方法区:类的描述,常量等 2.

Tomcat性能优化及JVM内存工作原理

Java性能优化原则:代码运算性能.内存回收.应用配置(影响Java程序主要原因是垃圾回收,下面会重点介绍这方面) 代码层优化:避免过多循环嵌套.调用和复杂逻辑.   Tomcat调优主要内容如下: 1.增加最大连接数 2.调整工作模式 3.启用gzip压缩 4.调整JVM内存大小 5.作为Web服务器时,与Apache整合或Nginx 6.合理选择垃圾回收算法 7.尽量使用较新JDK版本   生产配置实例: 1 2 3 4 5 6 7 8 9 10 11 12 13 <Connectorpor

java中JVM内存管理(1)

Java岗位面试,JVM是对程序员基本功考察,通常会问你对JVM了解吗?  可以分几部分回答这个问题,首先JVM内存划分 | JVM垃圾回收的含义  |  有哪些GC算法  以及年轻代和老年代各自特点等等 1) JVM内存划分: ①  方法区 (线程共享)  常量  静态变量  JIT(即时编译器)编译后代码也在方法区存放 ② 堆内存(线程共享) 垃圾回收的主要场地 ③  程序计数器  当前线程执行的字节码的位置指示器 ④   Java虚拟机栈(栈内存) :保存局部变量,基本数据类型以及堆内存中

JVM内存区域

JVM 内存划分 栈 虚拟机栈 本地方法栈 堆 方法计数器 方法区 对象的分配 指针碰撞 空闲列表 (√) 分配内存 线程安全问题: 分配动作处同步---实际上采用CAS保证分配的原子性 TLAB 本地线程分配缓存 对象内存中的信息布局 对象头 Mark word (根据对象状态复用此部分空间) hashcode GC分代信息 锁状态信息 线程持有的锁 偏向线程ID 偏向时间戳 ..... 类型指针(对象指向它的类元数据的指针,虚拟机可以通过这个指针来确定这个对象是哪一个类的实例) 实例数据 对

一、JVM内存之GC

1.JVM内存划分为堆内存和非堆内存 2.堆内存用途:存放对象,垃圾收集器就是收集这些对象,然后根据GC算法回收. 3.非堆内存用途:永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据.方法.常量.属性等. 元数据: calss的文本,路径等类属性: static属性类方法; 在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存. 4.JDK1.8为什么要废弃永久代?