0

0

JAVA虚拟机(JVM)详细讲解(二)——内存的划分

王林

王林

发布时间:2019-08-24 13:44:43

|

3705人浏览过

|

来源于CSDN

转载

我们知道,在c++语言里,如果想使用一个对象,需要对其进行new操作;如果不用这个对象了,需要对其进行delete操作。一旦开发人员忘记写delete语句了,就会造成内存泄露。【内存被对象占用着不还,就叫内存泄露。】

而java就聪明了,它从“手动”进化成了“自动”,把内存的控制权力交给了虚拟机。下面我们就来窥探一下jvm是怎么进行自动内存管理的。

20190618160941259.png

自动内存管理分为两部分

给对象分配内存和回收分配给对象的内存。在本篇我们说说前者,也就是内存划分和内存分配。下篇再说GC(垃圾回收)。

立即学习Java免费学习笔记(深入)”;

1、内存划分

我们来看看虚拟机内存里都有什么东西。JVM的内存区域大致分为Class文件、类装载子系统、运行时数据区、执行引擎。今天我们只说说运行时数据区。【这张图是基于JDK7的。JDK7以前,常量池是存放在方法区的。从JDK7以后,常量池放到了堆中。】

20190618154647817.png

线程公有

在运行时数据区中,方法区和堆是属于线程公有的,也就是这两块区域是“循环利用”的,所以要对其进行垃圾回收。其是在虚拟机启动时创建。

线程私有

虚拟机栈、本地方法栈、程序计数器是属于线程私有的,其与线程“同生死”,属于“一次性”的,所以不用对其进行垃圾回收。

(一)方法区

存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
其中有一个运行时常量池。其存储的是Class文件中描述的符号引用,直接引用。在编译期和运行期都可以将新的常量放入此池子中。

(2) 堆

概念:如果说栈解决的是程序运行问题,即程序如何处理数据;则堆解决的是数据存储问题,即数据怎么放,放在哪。

特点:

a、堆是虚拟机内存中最大的一块,大概占内存的四分之三。比如一个32位windows平台中每个进程有2GB的内存,则一般将1.5GB的内存划分给堆。可见堆的所占空间之大。
b、可处于物理上不连续的内存空间中,只要逻辑上是连续的即可。

作用:

存放对象实例,几乎所有的对象实例都在这里分配内存。

分类:

从内存回收的角度看,分为新生代和老年代。
从内存分配的角度看,可划分出多个线程私有的分配缓冲区。

(3)虚拟机栈

虚拟机栈里面存储的是栈帧,栈帧里面存储的是局部变量表,操作数栈,动态链接,方法出口等信息。

20190618170100488.png

栈中的栈帧

每个方法在执行的同时都会创建一个栈帧,一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

栈帧中的局部变量表

存放的是编译期可知的各种基本数据类型,对象引用,returnAddress类型。所以其所需的内存空间在编译期间就能完成分配,在运行期间不会改变其大小。

在分配基本数据类型所占的空间时,除了64位的long和double类型的数据会占用2个局部变量空间,其余的数据类型只占用1个。

(4)本地方法栈

本地方法栈和虚拟机栈的作用是相同的,只不过虚拟机栈执行的是java方法,本地方法栈执行的是Native方法。
java方法就是开发人员写的java代码,Native方法就是一个java调用非java代码的接口。

(5)程序计数器

程序计数器中存放的是当前线程所执行的字节码的行号。jvm工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

2、内存分配

这部分我们说说对象在java堆中是如何分配,布局和访问的,以及内存分配的原则。

Removal.AI
Removal.AI

AI移出图片背景工具

下载

对象的创建

我们用new来创建对象,来看看系统运行到new时,虚拟机在干什么。此时的类就像一块肉,他要经过层层安检,才能到达人类的饭桌。第一步:查看在常量池中是否有对应的符号引用。【在方法区中进行】

第二步:查看此类是否被加载,解析和初始化过。【在方法区中进行】

第三步:领取新生对象的内存。有两种方式:指针碰撞和空闲列表。【在堆中进行】

第四步:将分配到的内存空间初始化为零值。

第五步:对对象进行必要的设置,比如其是哪个类的实例,对象的哈希码之类的。这些信息存放在对象的对象头之中

第六步:如果java代码中对对象进行了赋初值,则会进行第六步:执行方法。此方法的作用就是对对象进行初始化。

对象的内存布局

对象在内存中的存储布局分为3部分:对象头+实例数据+对齐填充

对象头

对象头里面有两部分信息:

(1)运行时数据,包括哈希码,GC分代年龄,锁状态标志等。

(2)类型指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

实例数据

实例数据中存放的是代码中定义的各种类型的字段内容。

对齐填充

对齐填充起的是占位符的作用,不是必然存在的。其只要保证对象的大小是8字节的整数倍即可。

对象的访问定位

建立完对象后,我们就可以使用对象了。在使用时,怎么才能找到想找的对象?有两种方式:句柄和直接指针

句柄:

句柄访问就是在java堆中划分出一块内存来作为句柄池,句柄中包含了对象实例数据和类型数据各自具体的地址信息。

20190618201352170.png

直接指针:

直接指针之所以“直接”,是因为它去除了句柄这个中介。所以在速度上比句柄快。在HotSpot虚拟机中,使用的是这种方式。

20190618201408896.png

说完了对象在java堆中是如何分配,布局和访问的,接下来我们说说内存分配的原则

内存分配的原则:

20190618202533861.jpg

堆大致分为新生代,老年代,永久代。对象的内存分配主要分配在新生代的Eden区,少数情况下会直接分配到老年代中。分配的规则不是100%固定的,取决于垃圾收集器组合和参数设置等。下面有几条分配原则可供参考。

(1)对象优先在Eden分配。

(2)大对象直接进入老年代。

(3)长期存活的对象将进入老年代。

(4)动态对象年龄判定。

(5)空间分配担保。

以上便是JAVA虚拟机中关于内存的划分部分,更多问题请访问PHP中文网:JAVA视频教程

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

37

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

37

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

9

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号