标签:连续 serial 工作 gen 默认 code 管理系 地方 国际
JVM中的对象。
检查加载 -> 分配内存 -> 内存空间初始化 -> 设置 -> 对象的初始化
虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那么必须先执行相应的类加载过程。
根据方法区的信息确定为该类分配的内存空间大小。
但是分配内存时主要注意两个问题
1、如何分配空间
选择哪种分配方式由 Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定。
2、修改指针时如何实现线程安全
注意不是构造方法
内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(如 int 值为 0,boolean 值为 false 等等)。这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
接下来,虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。这些信息存放在对象的对象头之中。
在 HotSpot 虚拟机中,对象在内存中存储的布局可以分为 3 块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
1、对象头
2、实例数据
实例数据是对象真正存储的有效信息:代码中定义的各种类型的字段内容(包含父类继承的和子类定义的,都需要记录下来)。
3、对齐填充
对齐填充并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。
由于 HotSpot VM 的自动内存管理系统要求对对象的大小必须是 8 字节的整数倍,所以当对象其他数据部分(对象实例数据)没有对齐时,就需要通过对齐填充来补全。
例如:对象头大小为8字节,实例数据为5字节,那么实例数据就需要通过对齐填充来将实例数据补全成8字节。
建立对象是为了使用对象,我们的 Java 程序需要通过栈上的 reference 数据来操作堆上的具体对象。目前主流的访问方式有使用句柄和直接指针两种。
1、句柄:Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息。
2、直接指针:如果使用直接指针访问, reference 中存储的直接就是对象地址。
3、对比
注: 设置两个 Survivor 区是为了解决碎片化的问题(复制回收算法)。
一些分配规则
堆的大小可以通过如下参数设置
1、对象优先在Eden分配。
大多数情况下,对象在新生代 Eden 区中分配。当 Eden 区没有足够空间分配时,虚拟机将发起一次 Minor GC。
2、大对象直接进入老年代。
3、长期存活的对象将进入老年代。
如果对象在 Eden 出生并经过第一次 Minor GC 后仍然存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1,对象在 Survivor 区中每熬过一次 Minor GC,年龄就增加1,当它的年龄增加到一定程度(默认为15)时,就会被晋升到老年代中。
4、动态对象年龄判定
如果在 Survivor 空间中相同年龄所有对象大小的综合大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代。
5、空间分配担保
Java 语言中的泛型,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此,对于运行期的 Java 语言来说,ArrayList<int>与 ArrayList<String>就是同一个类,所以泛型技术实际上是 Java 语言的一颗语法糖,Java 语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。
举例说明:
public class Jvm3 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("SunnyBear","22");
System.out.println(map.get("SunnyBear"));
}
}
经过 javac 编译成.class文件后,使用反编译工具查看会发现泛型都不见了,变成了原生类型。
public class Jvm3 {
public static void main(String[] args) {
Map<String, String> map = new HashMap();
map.put("SunnyBear", "22");
System.out.println((String)map.get("SunnyBear"));
}
}
都读到这里了,来个 点赞、评论、关注、收藏 吧!
文章作者:IT王小二
首发地址:https://www.itwxe.com/posts/1e06d641/
版权声明:文章内容遵循 署名-非商业性使用-禁止演绎 4.0 国际 进行许可,转载请在文章页面明显位置给出作者与原文链接。
标签:连续 serial 工作 gen 默认 code 管理系 地方 国际
原文地址:https://www.cnblogs.com/itwxe/p/14875103.html