前言
类加载到系统之后,我们需要使用它的时候,构建对象。如何构建对象
new关键字
我们要使用一个类的对象,就需要先创建它的对象,创建有五种方式,但是我们最常用的是new。
DemoApplication demo = new DemoApplication();
//demo对象创建的字节码
0: new #10 // class com/bean/anotation/ownanotation/DemoApplication
3: dup
4: invokespecial #15 // Method "<init>":()V
7: astore_1
Java为什么可以跨平台
java在编译期没有直接编译成机器码(各平台汇编语言不同),而是字节码,字节码由JVM提供,所以只要安装了对应平台的jdk,都可以运行同一个java系统软件。一处编写,多处运行。这个跨平台由JVM实现,它为不同平台编写了不同的汇编模板解释器来解释字节码。
JVM有两种解释器:
- Zero字节码解释器,一种是基于switch-and-dispatch,也就是我们常用的switch语句对256条字节码指令进行解析。但很低效
- 汇编模板解释器,字节码指令直接对应汇编指令语句,不就是当前可实现的最快速度么。也正是jvm在使用。
Zero字节码解释器
我们看new关键字是如何被解释的用Zero解释器更好理解。入口在src/hotspot/cpu/zero/zeroInterpreter_zero.cpp的main_loop方法。主要程序在
src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp
CASE(_new): {
/**
* pc计数器用来存放当前欲执行指令的地址,它与主存的MAR之间有一条直接通路,且具
* 有自加1的功能,即可形成下一条指令的地址。
* pc计数器当前字节码指令地址,该位置存放的是new指令代码0xbb(187),
* pc+1刚好是new指令的参数地址:这个参数就是目标类符号引用在常量池中的索引
* 值,所以把这个值转成无符号整型,java是大端序,cpu小端序,它读取字节码数据时
* 自然认为是小端序,那么存储的时候就是当前顺序存,取的时候,它就把高地址位数据
* 当作高位,低地址位数据当做低位。这样就和我们本意颠倒了,所以需要翻转
* (indexbyte1 << 8) | indexbyte2。这也是JVM规范对于 new指令的定义介绍
* 过,常量池索引怎么计算。
*/
/**获取操作数栈中目标类的符号引用在常量池中的索引。例子中的#10
* pc是当前new指令指针,pc+1就是参数首地址也就是常量池索引的物理首地址。通过
* get_Java_u2把它存储的2字节数据取出来。
*/
u2 index = Bytes::get_Java_u2(pc+1);
// Attempt TLAB allocation first.
//
// To do this, we need to make sure:
// - klass is initialized
// - klass can be fastpath allocated (e.g. does not have finalizer)
// - TLAB accepts the allocation
//获取当前治理所在字节码文件的常量池
ConstantPool* constants = istate->method()->constants();
//开启了栈上分配并且目标类已经解析
if (UseTLAB && !constants->tag_at(index).is_unresolved_klass()) {
Klass* entry = constants->resolved_klass_at(index);
InstanceKlass* ik = InstanceKlass::cast(entry);
if (ik->is_initialized() && ik->can_be_fastpath_allocated()) {
size_t obj_size = ik->size_helper();
HeapWord* result = THREAD->tlab().allocate(obj_size);
if (result != NULL) {
// Initialize object field block:
// - if TLAB is pre-zeroed, we can skip this path
// - in debug mode, ThreadLocalAllocBuffer::allocate mangles
// this area, and we still need to initialize it
if (DEBUG_ONLY(true ||) !ZeroTLAB) {
size_t hdr_size = oopDesc::header_size();
Copy::fill_to_words(result + hdr_size, obj_size - hdr_size, 0);
}
oop obj = cast_to_oop(result);
// Initialize header
obj->set_mark(markWord::prototype());
obj->set_klass_gap(0);
obj->set_klass(ik);
// Must prevent reordering of stores for object initialization
// with stores that publish the new object.
OrderAccess::storestore();
SET_STACK_OBJECT(obj, 0);
UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
}
}
}
// Slow case allocation
CALL_VM(InterpreterRuntime::_new(THREAD, METHOD->constants(), index),
handle_exception);
// Must prevent reordering of stores for object initialization
// with stores that publish the new object.
OrderAccess::storestore();
SET_STACK_OBJECT(THREAD->vm_result(), 0);
THREAD->set_vm_result(NULL);
UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
}