Java对象在虚拟机中的创建、内存分布、访问定位以及死亡判定
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6535156.html
一:虚拟机中对象的创建
1:虚拟机遇到new指令时,在常量池检索是否有对应的符号引用,对应的类是否已加载、解析和初始化。没有则先加载对应的类文件到虚拟机。
2:加载类文件后,为新对象分配内存(内存大小在加载类后即可确定):有两种办法,取决于当前区域内存的情况
1)指针碰撞法:若内存是连续的,空闲内存和占用内存中间有一指针作为分界点,则分配内存时只需把指针往空闲区域移动相应大小即可;
2)空闲列表法:若内存中占用空间和空闲空间交错存在,则虚拟机维护一个表格记录各个空闲的块,在分配时从列表中找到足够大的空闲块并更新表格即可。
在多线程下为对象分配内存:把内存分配动作划分在不同的空间进行,每个线程在Java堆预先分配一小块内存作为自己的本地线程分配缓冲区(TLAB),之后哪个线程需要分配内存则在自己的TLAB中分配即可,用完了才需要在共享的堆中进行分配。而在共享的堆空间分配时,使用同步锁进行限制即可。
3:初始化分配的空间为零值。这一步保证了对象的实例在代码中无需赋初值即可使用。
4:为对象进行必要设置:把对象属于哪个类、元数据保存位置、哈希码、GC分代年龄等信息封装在对象头中。
5:对象初始化:执行init方法,根据程序员代码中的指令进行真正的赋值。
二:对象在内存中的存在形式
对象在内存中由三部分组成:对象头、实例数据、对齐填充。
对象头:包括两部分:
1)对象自身的运行时数据,包括:哈希码、GC分代年龄、锁状态标识、线程持有的锁、偏向线程ID等;
2)类型指针:指向对象所属类的元数据区域。
实例数据:对象真正的有效信息。
对齐填充:HotSpot虚拟机要求对象的起始地址必须是8字节的整数倍,因此对象的实例数据部分没有对齐时就需要对齐填充来补全。
三:对象的访问定位
我们通过方法中需要使用对象时,只需通过栈帧中的reference数据来访问堆中的对象内容即可。对象的访问有两种方法:句柄法、直接指针法。
句柄法:内存中划分一片区域作为句柄池,句柄池中的句柄包含了该对象到实例数据区域的指针以及到对象类型区域的指针。句柄法访问对象时,先通过reference定位到句柄池中该对象的句柄,然后由句柄中的两个指针分别访问该对象的具体实例数据和类型数据。
直接指针法:reference直接执行对象的实例数据区,而数据区中又有一个指针指向类型数据区域。
比较:句柄法比较文档,如果对象内容被移动的话,只需更改句柄池中的句柄即可,栈帧中的reference可以不改变;而直接指针法则速度更快。
四:对象已死?
判断对象是否还在内存中存活,有两种理论:
1)引用计数法:每当有一个引用执行该对象时,引用计数器+1.当计数器器的值为0时即说明对象没有被引用,已死亡。该理论的致命缺陷在于:两个对象互相引用时,彼此计数器值不为0,但又不再被访问,对象已无用却一直不会被回收。
2)可达性分析:通过一系列GCRoots对象作为起点,沿着这些节点的引用链进行检索。若一个对象没有任何引用链与GCRoots相连的话,即说明该对象不可达(不可用),可进行回收。GCRoots一般有:栈帧的引用对象、静态属性引用的对象、常量引用的对象、本地方法栈中引用的对象。
Java对象在虚拟机中的创建、内存分布、访问定位以及死亡判定的更多相关文章
- Java对象在JVM中的生命周期
当你通过new语句创建一个java对象时,JVM就会为这个对象分配一块内存空间,只要这个对象被引用变量引用了,那么这个对象就会一直驻留在内存中,否则,它就会结束生命周期,JVM会在合适的时 ...
- Java 对象在堆中的内存结构
翻译人员: 铁锚 翻译日期: 2013年11月8日 原文链接: What do Java objects look like in memory during run-time? 我们知道,函数每次 ...
- jvm详情——2、Java对象在jvm中的大小
Java对象的大小 基本数据的类型的大小是固定的,这里就不多说了.对于非基本类型的Java对象,其大小就值得商榷.在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任 ...
- json字符串转java对象,json中字段名称与对象属性名称不一致
json字符串转java对象,json字段名称与对象属性名称不一致可以在对象属性上添加注解@SerializedName解决
- 虚拟机中如何Linux系统如何访问PC硬盘中的文件(如何将windows下的文件夹挂载到linux虚拟机下)
这段时间决定学习嵌入式,变打算安装个Linux系统先熟悉一下Linux系统的使用,但自己电脑上安装的win7系统又不想装双系统,一是闲麻烦,二是由于对Linux系统不熟悉担心会因为自己的误操作而损坏系 ...
- JAVA虚拟机中的堆内存Heap与栈内存Stack
原文链接:http://www.cnblogs.com/laoyangHJ/archive/2011/08/17/gc-Stack.html 深入Java虚拟机:JVM中的Stack和Heap 在JV ...
- java在jvm虚拟机中是如何实现多态的?
原文地址:https://blog.csdn.net/huangrunqing/article/details/51996424 众所周知,多态是面向对象编程语言的重要特性,它允许基类的指针或引用指向 ...
- 关于Java客户端连接虚拟机中的Kafka时,无法发送、接收消息的问题
kafka通过控制台模拟消息发送和消息接收正常,但是通过javaAPI操作生产者发送消息不成功 消费者接收不到数据解决方案? 1.问题排查 (1)首先通过在服务器上使用命令行来模拟生产.消费数据,发现 ...
- Java核心知识点 --- 线程中如何创建锁和使用锁 Lock , 设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
随机推荐
- Java枚举的七种常见用法
用法一:常量 在JDK1.5之前,我们定义常量都是:publicstaticfianl.....现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法. Java代码 ...
- [Web 前端] 使用yarn代替npm作为node.js的模块管理器
cp from : https://www.jianshu.com/p/bfe96f89da0e Fast, reliable, and secure dependency managemen ...
- 【转】windows下mongodb安装与使用整理
转自 :http://www.cnblogs.com/lecaf/archive/2013/08/23/mongodb.html 一.首先安装mongodb 1.下载地址:http://www.mon ...
- [转]微信JSAPI 微信内置JSAPI 2015年1月官方正式API接口,分享完整实例
FROM : http://www.oschina.net/code/snippet_2276613_45290 HTML通过微信,分享朋友圈出发此JSAPI <?php require_onc ...
- ThinkPHP错误信息处理
index.php入口文件中打开APP_DEBUG// 开启调试模式define('APP_DEBUG', TRUE); // 开启Trace信息 'SHOW_PAGE_TRACE' =>tru ...
- CentOS下httpd下php 连接mysql 本机可以,外网报错Could not connect: Can't connect to MySQL server on '127.0.0.1' (13)2003 原因解析
php代码很简单: $server="127.0.0.1"; println("Begin"); $link = mysql_connect($server,& ...
- 7.4 服务远程暴露 - 创建Exporter与启动netty服务端
为了安全:服务启动的ip全部使用10.10.10.10 远程服务的暴露总体步骤: 将ref封装为invoker 将invoker转换为exporter 启动netty 注册服务到zookeeper 订 ...
- 在ASP.NET MVC中以post方式传递数组参数的示例【转】
最近在工作中用到了在ASP.NET MVC中以post方式传递数组参数的情况,记录下来,以供参考. 一.准备参数对象 在本例中,我会传递两个数组参数:一个字符串数组,一个自定义对象数组.这个自定义对象 ...
- 遛老虎网 http://6laohu.com/
遛老虎网 http://6laohu.com/
- Mysql写入中文出错
本地调试好像正常,服务器运行报错: UnicodeEncodeError: 'latin-1' codec can't encode character u'\u5206' in position 2 ...