对象实例化
new 方式,变形1、2是要创建的对象的构造方法是私有的,不能直接构造对象,只可以通过该类方法或者其他类的静态方法构造。
反射的方式,只可以使用无参且由public修饰的
@CallerSensitive public T newInstance() throws InstantiationException, IllegalAccessException {
任何修饰符、任何参数都可以使用
@CallerSensitive public T newInstance(Object ... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
字节码角度查看对象创建
public class ObjectTest {
public static void main(String[] args) {
String s = new String();
}
}
字节码指令
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
从字节码指令结合执行过程进行分析
- 0: new 对应的就是判断对象是否加载,如果没有就是对象的加载、链接、初始化
为对象分配空间
。。。。一直到第6步
3: dup 是复制引用(暂时没讲为什么?)
4: invokespecial #3 执行init方法,创建对象
7: astore_1 引用保存到堆内存
对象的内存布局
对象头
举例
内存布局
对象访问定位
两种方式
1.句柄访问
优点:稳定,reference不会改变,当实例对象地址改变,只需要改动句柄池当中数据。
缺点:访问速度慢,需要在堆内存开辟更多的空间
2.直接访问(hospot虚拟机使用的)
优点:访问实例速度慢,不需要在堆内存开辟更多的空间
缺点:不稳定,reference会改变。