深入了解java虚拟机(JVM) 第四章 对象的创建

一、对象的创建过程

    对象的创建过程大致可以分为六步,其中对象的分配尤为重要:

         

二、对象分配内存

       一般来说对象分配内存有两种方式:

        第一种是指针碰撞,这是一种比较理想的方式:如果Java堆是绝对规整的:一边是用过的内存,一边是空闲的内存,中间一个指针作为边界指示器;分配内存只需向空闲那边移动指针,这种分配方式称为"指针碰撞"(Bump the Pointer);

       第二中方式是空闲列表,这中方式没有指针碰撞那么理想,但是也有他自身的优势:如果Java堆不是规整的:用过的和空闲的内存相互交错; 需要维护一个列表,记录哪些内存可用;分配内存时查表找到一个足够大的内存,并更新列表,这种分配方式称为"空闲列表"(Free List);

      这两种方式各有各的优势,具体选用方式,需要根据垃圾收集器来进行选择,主要是根据垃圾回收器有无压缩来选择。

三、线程安全问题

      在进行并发操作时,上面两种方式分配内存的操作都不是线程安全的,所以考虑到解决这种线程安全问题:

      第一种:加锁,这种方式是开发过程中最容易使用的方式,也是最简单的方式,但是这种方式的缺点就是执行效率太低。

      第二种:本地线程分配缓冲区(TLAB):把分配内存的动作按照线程划分在不同的空间中进行:在每个线程在Java堆预先分配一小块内存,称为本地线程分配缓冲区(Thread Local Allocation Buffer,TLAB);哪个线程需要分配内存就从哪个线程的TLAB上分配。

四、对象的结构

     对象的结构分为三部分:

      第一部分:Header(对象头),对象头又有两给部块组成

       1.自身运行时数据(Mark word),这部分数据是对象主要存储的数据,主要有:

                a.哈希值:这个值是通过一个native方法获取

                  b.GC分代年龄:这个是垃圾回收算法使用

           以上介绍两种作用是太相同的,至于剩下的:c.锁状态标志、d.线程持有的锁、e.偏向线程ID、f.偏向时间戳都是作用于线程优化的

       2.类型指针:对象指向类对象本身数据的指针

      第二部分:实例数据(InstanceData):

         实例数据部分是对象真正存储的有效信息,也既是我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的都需要记录下来。 这部分的存储顺序会受到虚拟机分配策略参数(FieldsAllocationStyle)和字段在Java源码中定义顺序的影响。HotSpot虚拟机 默认的分配策略为longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers),从分配策略中可以看出,相同宽度的字段总是被分配到一起。在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。如果 CompactFields参数值为true(默认为true),那子类之中较窄的变量也可能会插入到父类变量的空隙之中。

    第三部分:对齐填充(Padding)

       第三部分对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说就是对象的大小必须是8字节的整数倍。对象头正好是8字节的倍数(1倍或者2倍),因此当对象实例数据部分没有对齐的话,就需要通过对齐填充来补全。

五、对象的访问定位

     对立对象是为了使用对象.Java程序需要通过在栈上的reference数据操作堆上的具体对象. 由于reference类型在Java虚拟机规范中只规定了一个指向对象的引用,并没有定义这个引用应该通过何种方式去定位,访问堆中的对象的具体位置,所以对象的访问方式取决于虚拟机的实现而定的.。简单来说 栈指向堆中只会指向地址,至于地址存储的是否对象,我们是无法知道的,

    解决这一问题目前有两种方式:

      第一种:句柄指针:栈指向堆中的句柄池,句柄池中有实例对象的地址,通过句柄池指向对象

      优点:栈地址永远不会改变,或者说引用地址不会改变

      第二张:直接指针:reference中存储直接对象的地址,但是必须考虑放置访问类型数据的相关信息

     优点:效率快,节省了一次指针定位的时间开销

 

转载于:https://www.cnblogs.com/daijiting/p/9960783.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/570159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LODOP使用问题解决汇总

LODOP 打印控件出现问题及修改方法 问题1 、打印网页时页面出现电脑设置的底色如何解决&#xff1f; 解决方法 &#xff1a;按照如下方式添加HTML页面 var strHTML"<body stylemargin:0;background-color: white>"document.getElementById("table02&qu…

[UWP]使用Picker实现一个简单的ColorPicker弹窗

[UWP]使用Picker实现一个简单的ColorPicker弹窗 原文:[UWP]使用Picker实现一个简单的ColorPicker弹窗在上一篇博文《[UWP]使用Popup构建UWP Picker》中我们简单讲述了一下使用Popup构建适用于MVVM框架下的弹窗层组件Picker的过程。但是没有应用实例的话可能体现不出Picker相对于…

java sort排序

问题&#xff1a;对list中的对象中的属性值排序&#xff1a; User对象&#xff1a; public class User {private int id;private String Name; public int getid() {return id;}public void setid(int id) {this.id id;}public String getName() {return Name;}pub…

C# WebRequest.Create 锚点“#”字符问题

背景 在与后台API接口对接时&#xff0c;如将网页Url作为参数请求数据时&#xff0c;如果是锚点参数&#xff0c;则会丢失。 锚点参数 请求通过WebRequest.Create创建一个WebRequest&#xff1a; 1 var uri "https://id.test.xxx.com/api/v1/auth/sso/url?redirectUrlht…

Postgresql 按30分钟、小时、天分组

按30分钟统计&#xff1a; shool_time格式为varchar&#xff0c; 例如 201911050808、201911050820、201911050842 分组后结果&#xff1a; 20191105 0800 20191105 0830 20191105 0900 20191105 0930 注&#xff1a;小于30分钟的按00统计&#xff0c;大于30分钟的按30统计 SEL…

Java calendar加减时间

//时间格式可以改成自己想要的格式&#xff0c;例yyyy-MM-dd HH:mm等等。 private final static String formatyyyyMMddHHMM "yyyyMMddHHmm";String currTime "201911051500";SimpleDateFormat yearFormat new SimpleDateFormat(formatyyyyMMddHHMM); D…

免费的编程中文书籍索引(2018第三版)

之前我在 github 上整理了来一份&#xff1a;free-programming-books-zh_CN&#xff08;免费的计算机编程类中文书籍&#xff09;。 截至目前为止&#xff0c;已经在 GitHub 收获了 40000 多的 stars&#xff0c;有 90 多人发了 600 多个 Pull Requests 和 issues。 在收集的过…

java中Map ListE的用法

返回的restful接口数据样式&#xff1a; {party: [{"finishTime": "20191105","busiCnt": 1000}]}1、定义WzwScreenEntity 实体 public class WzwScreenEntity {private String finishTime;private String busiCnt;private String party;publi…

ORM是什么?如何理解ORM?

一、ORM简介 对象关系映射&#xff08;Object Relational Mapping&#xff0c;简称ORM&#xff09;模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说&#xff0c;ORM是通过使用描述对象和数据库之间映射的元数据&#xff0c;将程序中的对象…

遍历Map keySet和entrySet

public class test {public static void main(String[] args) {Map<String, String> map new HashMap<String, String>();map.put("1", "广东");map.put("2", "广西");map.put("3", "广南");map.put…

falcon适配ldap密码同步

问题 小米的openfalcon在使用ldap首次登陆成功后,会在本地创建同名的账号, 这就有个问题当你更新了ldap的密码时,openfalcon是没有同步本地账号密码的功能 二次改造 方便我们debug, 先把日志的debug打开,默认是没有运行时日志的,只有console日志 # 编辑文件 dashboard/rrd/util…

如何有效的使用 for循环和Iterator遍历

遍历ArrayList 使用for循环遍历的速度会比Iterator遍历的速度要快&#xff1a; for (int i0, nlist.size(); i < n; i)list.get(i);runs faster than this loop:for (Iterator ilist.iterator(); i.hasNext();)i.next();采用ArrayList对随机访问比较快&#xff0c;而for循环…

【js】数组置空的其他方式及使用场景

数组在js中属于引用型类型。 var arr [1, 2, 3]; a []; 通常使用以上方式。如果使用场景必须使用方法置空&#xff0c; 可以采用arr.length 0; 或者使用a.splice(0, a.length); 使用场景 vue2中组定义组件中v-model的值是数组类型&#xff0c; 组件内部需要清空时&#xff0…

Postgresql 填充所有的时间点

最近使用有个业务需要展示20190101和20190106所有的时间段&#xff0c;例如 20190101 20190102 20190103 20190104 20190105 20190106但是数据库中存的只有以下 20190101 20190102 20190104 20190106那我们需要把20190103、20190105填充进去。 方式一&#xff1a; 新建个存储…

分类与监督学习,朴素贝叶斯分类算法

1.理解分类与监督学习、聚类与无监督学习。 &#xff08;1&#xff09;简述分类与聚类的联系与区别。 分类就是按照某种标准给对象贴标签&#xff0c;再根据标签来区分归类。聚类是指事先没有“标签”而通过某种成团分析找出事物之间存在聚集性原因的过程。 区别是&#xff0c…

Postgre合并多行数据为一行

业务情景描述&#xff1a;用户需要一行展示所有的文件名称&#xff0c; 比如&#xff1a;你的1.txt、2.txt、3.txt未上传成功&#xff0c;请核查&#xff01; SELECT * FROM fileTable --查询结果如下&#xff1a; 1.txt 2.txt 3.txt方式一&#xff1a;使用string_agg函数&…

如何学好Spring

要学好Spring&#xff0c;首先要明确Spring是个什么东西&#xff0c;能帮我们做些什么事情&#xff0c;知道了这些然后做个简单的例子&#xff0c;这样就基本知道怎么使用Spring了。Spring核心是IoC容器&#xff0c;所以一定要透彻理解什么是IoC容器&#xff0c;以及如何配置及…

数据库查询字段为空时,返回0

oracle select nvl(字段名,0) from 表名; sqlserver select isnull(字段名,0) from 表名; mysql select ifnull(字段名,0) from 表名; postgresql select coalesce(字段名,0) from 表名;

一张图搞定OAuth2.0

转发&#xff1a;https://www.cnblogs.com/flashsun/p/7424071.html 目录 1、引言2、OAuth2.0是什么3、OAuth2.0怎么写1、引言 本篇文章是介绍OAuth2.0中最经典最常用的一种授权模式&#xff1a;授权码模式 非常简单的一件事情&#xff0c;网上一堆神乎其神的讲解&#xff0c;让…

insert select 过滤掉重复数据

INSERT INTO SELECT 语句从一个表复制数据&#xff0c;然后把数据插入到一个已存在的表中。 table1和table2表结构一样时&#xff1a; INSERT INTO table2 SELECT * FROM table1;table1和table2表结构不一样时&#xff1a; INSERT INTO table2(field1,field2,field3) SELECT …