当一个对象被创建了,那在JVM中是如何的从一个对象不存在到存到,然后将对象存放在什么地方呢?这次主要来探讨一下Java对象创建的过程。

new关键字创建对象的3个步骤:

1、在堆内存中创建出对象的实例。

当我们用new关键字来创建对象的实例时,JVM首先会检查new这个指令的参数是不是能造常量池中定位成一个类的符号引用,然后再检查该符号引用所对应的类是不是被正常的加载、连接、初始了,如果木有则必须要完成类的加载过程,当事先的准备阶段都结束之后,接着JVM则为该对象分配内存,当对像加载完之后该对象要分配多少内存其实是已经确定的一件事情了。而在Java堆中内存整体来说是分成2部分的,第一部分内存是已经被使用或者说已经被占用的,而第二部分内存则是空闲的可以被使用的,而已经被占用的空间和未被使用的空间又分为两种情况:

第一种情况:在堆内存中已经截然有序的将已使用和未使用的内存空间给分离开了,比如说左侧是已经占用的空间,而右侧是未被占用的空间。中间可以通过一个指针来指向,这种情况下如果新创建的对象则会存在于未被占用的空间中,然后指针发生了一个移动指向了下一个可以被使用的内存空间,对于这种case我们可以称之为指针碰撞(前提是堆中的空间通过一个指针进行分割,一侧是已经被占用的空间,另一侧是未被占用的空间)。

第二种情况:这种Java堆内存并未像第一种情况说得这么理想,而是不归整交织在一起了,这种情况下肯定不能去移动指针这么简单来进行指向了,这时需要记录一个列表用来标识哪些地方是内存已经被使用了的,哪些是未被使用了的,并且还要记录未被使用的大小是多少,这种情况下当要给对象分配内存时,则需要从列表中选出来可以容纳新创建对象大小的空间,然后把新的对象放置在可以容纳的内存当中,并且要修改列表的记录,这种做法则称之为空闲列表(前提是堆内存空间中已被使用与未被使用的空间是交织在一起的,这时,虚拟机就需要通过一个列表来记录哪些空间是可以使用的,哪些空间是已被使用的,接下来找出可以容纳下新创建对象的且未被使用的空间,在此空间存放该对象,同时还要修改列表上的记录)

FAQ:为啥会有这两种情况呢?其实是跟垃圾收集【未来会专门学到它】器息息相关的,有一些垃圾收集器是带压缩过程,所谓压缩过程是指垃圾收集器在执行一次垃圾回收的时候,除了把真正垃圾的对象给清除掉之外,此时已使用和未使用的内存一定是不连续的,那么它们在做完清除工作之后还要做一次对象的移动操作,也就是将已被使用的和未被使用的分文别类的给排开,此时就可以用指针碰撞的方式来解决对象存放的问题;而有些垃圾收集器在垃圾回收之后就立马结束了,不会对对象进行一个移动操作,从而导致已使用和未被使用的内存交织在一起的,此时就只能用空闲列表的方式来解决对象存放的问题啦。

2、为对象的实例成员变量【而非静态成员变量】赋初值。

这个不多解释了,在之前的类加载中详细说过。

3、将对象的引用返回。

对象在内存中的布局【了解既可】:

对象的内存布局其实就是指一个对象它存放的信息有啥, 总共分为三部分:

1、对象头。

它会存放对象自身的一些运行时的数据信息,比如说一个对象有一个hash码、还有分代的一个信息等,把这些信息都放置在对象头里面。

2、实例数据 (既我们在一个类中所声明的各项信息)。如成员变量。

3、对齐填充(可选),其实就是起到一些点位符的作用,比如说要求8的倍数,如果不够8的话被0等。

引用访问对象的方式:

这个在之前【https://www.cnblogs.com/webor2006/p/9876493.html】已经详细学习过了,其实就是两种形态,回顾一下:

1、使用句柄的方式。

2、使用直接指针的方式。

这两种有啥区别,这里也再贴出来回顾一下,纯之前学的东东:

好,接下来回到咱们熟悉的代码上来,上面一大堆的理论还得由实践将其进行验证,这里编写一个可以在堆空间出现内存溢出异常的代码,具体做法如下:

也就是写一个死循环,不断的往堆中新建MyTest1对象,最终肯定会撑爆JVM的堆空间从而来模拟出堆内存溢出,我们知道JVM是可以有参数来调整截内存空间的,为了让这个程序更快的出现,我们可以手动来修改JVM的参数,如下:

其中还设置了一个当发生内存溢出时来将内存的信息给dump出来,其实就类似于Android中来分析内存也是需要dump内存信息一样,如下:

下面来运行一下,看是不是很快就报内存溢出异常了:

立竿见影嘛,其中内存异常的原因也可以清楚的看到是由于java的堆空间:

其中可以看到dump文件已经创建了:

那咱们在工程中刷新一下,发现貌似木有看到dump文件呀,其实在IntelliJ IDEA中是没有将其显示出来而已,咱们得在目录文件中来查看,瞅下:

那dump文件生成了怎么查看呢,莫要急,下次再继续学~~

Java对象内存分配原理与布局的更多相关文章

  1. Java 对象内存分配与回收

    JVM内存区域模型: * 程序计数器,内存区域极小,是当前线程的字节码执行行号指示器: * 虚拟机栈.本地方法栈,即平时所说的“栈”,是虚拟机用来执行方法(包括Java.非Java方法)时,使用的临时 ...

  2. Java对象内存布局

    本文转载自Java对象内存布局 导语 首先直接抛出问题 Unsafe.getInt(obj, fieldOffset)中的fieldOffset是什么, 类似还有compareAndSwapX(obj ...

  3. 深入Java核心 Java内存分配原理精讲

    深入Java核心 Java内存分配原理精讲 栈.堆.常量池虽同属Java内存分配时操作的区域,但其适用范围和功用却大不相同.本文将深入Java核心,详细讲解Java内存分配方面的知识. Java内存分 ...

  4. java内存分配原理

    一般Java在内存分配时会涉及到以下区域: ◆寄存器:我们在程序中无法控制 ◆栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 ◆堆:存放用new产生的数据 ◆静态域:存放在 ...

  5. [Java]Java类和对象内存分配详解

    描述 代码说明: 一.当Person p1 = new Person();第一次被调用时需要做两件事: 1.先判断类加载器是否加载过Person类,如果没有则加载到Person类型到方法区 2.在堆中 ...

  6. java中内存分配策略及堆和栈的比较

    Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...

  7. JAVA虚拟机内存分配与回收机制

    Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现.Java虚拟机有自己想象中的硬件,如处理器.堆栈.寄存器等 ...

  8. JVM内存分配原理

    堆栈常量池等内存分配原理详解 存储的方式: 寄存器 栈(stack) 堆(heap) 静态域 常量池 非RAM存储 JAVA寄存器 最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.  ...

  9. [Java] 监控java对象回收的原理与实现

    监控Java对象回收的原理与实现 一.监控Java对象回收的目的 监控Java对象是否回收的目的是:为了实现内存泄露报警. 内存泄露是指程序中对象生命周期(点击查看详情)已经进入不可见阶段,但因为编码 ...

随机推荐

  1. Selenium2+python自动化2.7-火狐44版本环境搭建(转)

    转载地址:https://www.cnblogs.com/yoyoketang/p/selenium.html 前言 目前selenium版本已经升级到3.0了,网上的大部分教程是基于2.0写的,所以 ...

  2. 解决Adobe cs6系列软件在Windows10操作系统中无法正常运行问题

    大家好,我是安德风,很高兴今天能给大家一起解决Adobe cs6系列软件在Windows10操作系统中无法正常运行的问题.今天我以Adobe Photoshop cs6在Windows10环境安装运行 ...

  3. Swoole练习 安装

    仅支持 Linux,FreeBSD,MacOS,3类操作系统 Linux 内核版本 2.3.32 以上 PHP-5.3.10 以上版本,包括PHP7 gcc4.4 以上版本或者clang cmake2 ...

  4. Spark 基础操作

    1. Spark 基础 2. Spark Core 3. Spark SQL 4. Spark Streaming 5. Spark 内核机制 6. Spark 性能调优 1. Spark 基础 1. ...

  5. [转帖]linux操作系统测试工具

    linux操作系统测试工具 http://cfdtesting.com/879156.html 作者: minions_222      来源: CFDTesting.com采编      发布于:  ...

  6. 使用mybatis完成增删改查

    插入 插入数据 <insert id="insertUser2" parameterType="UserEntity"> insert into u ...

  7. 如何实现在H5里调起高德地图APP

    这一篇文章将告诉您,如果直接打开高德地图APP,并展示路线规划.适合有定位的移动设备,可以查询到从“我的位置”到目的地的路径规划,并直接导航. 场景二.调起高德地图的路线规划功能 导航是目前JSAPI ...

  8. 动态script标签同步加载 ps:无打包编译,静态实现静态资源入口动态配置,无编译打包静态资源添加版本号

    /**功能:创建动态标签加载css ,js文件,重点是js文件,利用onloading加递归实现动态标签的同步加载用法:在html文件body底部script内部声明并调用下列函数,obj中写要加载的 ...

  9. Educational Codeforces Round 64 (Div. 2)

    A.3*3讨论即可,注意正方形套圆套三角形只有6个点. #include<cstdio> #include<cstring> #include<iostream> ...

  10. Dockfile文件解析

    1. Dockerfile内容基础知识 每条保留字指令都必须为大写字母且后面要跟随至少一个参数 指令按照从上到下,顺序执行 #表示注释 每条指令都会创建一个新的镜像层,并对镜像进行提交 2. Dock ...