有的面试官会挖这个坑:你说说遇到的错误
java
Exception
- 是异常,是代码里经常写的Error
- 是错误,像内粗溢出 OOM 这样的就是坏就坏在你可能没注意说成另外一个了,的确有这样坏心眼的家伙(╯‵□′)╯︵┴─┴面试
类的使用能够分主动使用、被动使用,区别是被动使用类时,不会致使类的初始化,这会致使不少难以查找的 Bug 的算法
经过new关键字、反射、clone、反序列化机制实例化对象
调用类的静态方法时
使用类的静态字段或对其赋值时
经过反射调用类的方法时
初始化该类的子类时(初始化子类前其父类必须已经被初始化)
JVM启动时被标记为启动类的类(简单理解为具备main方法的类)
new
用new语句bai建立对象,这是最常du用的建立对象的方式。Class.newInstance()
,JDK9 之后过期了,只能使用public的无参构造方法Construtcor.newInstance(xx)
有参无参均可以,也没有访问限制,这就是反射的好处clone()
反序列化手段:
好比IO,ObjectInputStream 的readObject() 方法,从本地文件,或者网络上获取第三方库Objenesis
利用字节码技术,动态生成class信息这个你们了解,知道有这么回事就行,注意反射的2种方式差异,实际场景会用上数据库
public class Max {
public void run() {
String name = new String();
}
}
复制代码
字节码:网络
public void run();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class java/lang/String
3: dup
4: invokespecial #3 // Method java/lang/String."<init>":()V
7: astore_1
8: return
LineNumberTable:
line 11: 0
line 12: 8
复制代码
一般这个问题是和 volitale 保证有序性、单例模式的双判断写法为何还要加上 volitale 关键字这个问题联系在一块儿问的并发
判断对象对应的类是否被加载、连接、初始化了
也就是new指令会去方法区常量池中定位到类的符号引用,检查这个符号引用是否被加载了给对象分配内存空间,计算对象须要占用多大的内存空间
并发处理
堆内存是共享区域,就会有并发问题
-XX:UseTLAB
来设置初始化分配到的内存空间(默认初始化)
也就是给属性赋一个初始的默认值,即使该属性在代码里设置值了,在这一步也会先给一个默认值,在以后的步奏里再赋指定值设置对象头
对象头保存有对象的hashcode,GC信息,锁信息,所属类(方法区元数据地址)显示初始化,执行init方法并初始化
具体能够看下一个问题的解答,init就是类的构造器实际到代码spa
Dog dog = new Dog();
复制代码
new 关键字能够理解为1-5步,Dog() 至关于第6步线程
用过的内存在一边,没用过的内存在另外一边,中间临界点有一个指针。要是须要新分配内存空间了,只须要把指针移动执定大小便可。不过JVM是否采用这种分配方式,的看采用的垃圾回收器选择的是否是 Serial、ParNew 这样的压缩算法(标记整理)了。核心就是垃圾回收以后新生代伊甸园区的是规整过的才能这么玩 3d
属性的默认初始化
显示初始化/代码块初始化
构造器中初始化
上个问题6里面的init方法对应的就是这里的二、3部指针
有:句柄式、直接指针
2种
在JVM堆内存中,维护一个列表,存储每一个对象对应的内存地址,比如咱们在数据库搞一个索引表出来,你们要理解句柄的含义,就是索引,句柄是C++的内容,可是在java里好多地方还有她的身影
句柄的好处在这个索引表的内存地址是不变的,不论是对象的地址怎么变,对于别人来讲其实都是不变的
缺点是真用内存,访问效率低一些
这是目前 htospot 虚拟机访问对象的方式,不须要索引表,我直接记录你的内存位置,缺点是地址变了须要通知使用者
这道题仍是知道的好,还真就有人问。具体就是涉及到 GC 的标记清除算法上的优缺点,句柄式的能够并发的GC垃圾回收,由于句柄是不变的,我恩始终能够找到对象。直接指针GC咱们就必须中止其余线程,由于引用地址会变
这是一道常问的面试题,咱们只考虑通常对象,对象实体是空的,Mark Word 占64位8个字节
类型指针默认是8个字节的,可是在开启指针压缩时会变成4个字节,JDK8 是默认开启的
参考对齐方式,对象的大小必须能被8整除。因此一个空对象默认占用内存大小是12个字节,算上对齐方法的化是16个字节