类的初始化过程和对象分配过程也是面试中经常问的问题,如果能够清晰的回答出来必定涨分不少。

初始化过程

对象的初始化包含了类加载过程,所以这里相当于是讲类的加载过程,类加载过程分为7步:加载、验证、准备、解析、初始化、使用、卸载;

首先第一步加载过程就是通过类的权限定名称获取类的二进制流,JVM把二进制流文件中存储的静态结构转化成方法区运行时数据结构,然后生成这个类的Class对象,这个类的数据访问通过这个Class对象。

第二步是验证,主要是验证二进制流是否符合规范,主要分为文件格式验证、元数据验证、字节码验证、符号引用验证;

第三步是准备阶段,也就是为这个类的静态变量分配内存并设置默认值,这些都是随着类走的,所以是分配到方法区中。

第四步解析就是将一些符号引用换成正真要引用的对象,也就是直接引用。

第五步初始化就是执行我们编写在类中随着类走的代码,比如静态变量设置对应的值,静态代码块的执行。

类的初始化到这一步就基本完成了,剩下的就是对类进行使用了,通常的使用就是对类进行实例化,那么接下来就是对象使用时的分配过程。

对象分配过程

这里只讨论一个方法创建一个对象时的分配过程。首先要说明几个JVM运行时内存概念,首先是每个线程都有一个Java虚拟机栈,每个方法对应栈中的一个栈帧。在堆中会为每个线程分配一小段私有的的分配缓冲区 (Thread Local Allocation Buffer初始化,以下简称TLAB)。

当在方法中new一个对象的时候,首先会判断这个对象是否会逃逸,简单点说就是这个对象会不会被其他方法所使用,如果随着这个方法执行结束这个对象也就不会被其他任何地方引用,那么这个对象就可以被分配在这个方法对应的栈帧中,然后随着方法调用结束栈帧被回收,对象也同步被回收。

如果判断会逃逸那么就只能放到堆中了,会先判断对象的大小对象大小是否超过系统设置的进入老年代的大小,如果对象太大那么对象可能会直接分配到老年代,否则会分配到新生代中。

因为堆可以同时被多个线程申请内存,所以对象分配就涉及到了并发分配的问题,为了优化这个过程,堆为每个线程都分配了一段内存TLAB,对象会优先判断是否能够分配到这里面,如果TLAB内存足够容纳这个对象,则直接分配到TLAB中,就不用考虑并发分配的问题。

如果TLAB中分配失败对象就直接分配到新生代Eden中,如果通过一次回收后进入Survivor区,每次回收后都进入另外一个Survivor,如果经过多次回收仍然存活,当年龄达到新生代最大年龄时直接进入老年代,或者某次GC的时候被回收掉。

以上整体流程图如下图:

初始化电脑的后果_初始化是什么意思_初始化

对象是JVM中最重要的元素,对象的分配也是最多操作之一,所以对它也进行了多层次的优化,可以理解成方法能管理分配的那就方法分配管理(栈上分配),线程私有内存够的就线程内存中分配(TLAB分配),线程内存不够那就只能JVM统一管理了,通过这样一步一步扩散的过程减少了直接在堆中分配导致的垃圾回收(栈上分配不用垃圾回收)和并发(TLAB分配没有并发)问题。

总结

类的初始化过程我们不妨自己想想实现方案,然后对比JVM的实现方案就能够更加便于记忆和理解了,首先肯定是要找到并加载二进制文件,然后肯定要验证文件符不符合要求,在然后才是初始化里面的内容,只不过JVM是先设置的默认值,然后设置引用,最后才是正真的设置,这样一看过程还是挺简单的。

而对象的初始化,我相信大多数人都是知道对象在Eden、Servivor区的轮转,只不过JVM在方法和线程两个层面上进行了优化。


娜娜项目网每日更新创业和副业项目

网址:nanaxm.cn 点击前往娜娜项目网

站 长 微 信: nanadh666


Java程序员日常学习笔记初始化,如理解有误欢迎各位交流讨论!

初始化电脑的后果_初始化_初始化是什么意思


娜娜项目网每日更新创业和副业项目

网址:nanaxm.cn 点击前往娜娜项目网

站 长 微 信: nanadh666

声明: 本站内容转载于网络,版权归原作者所有,仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任,若侵犯到你的版权利益,请联系我们,会尽快删除处理!