HotSpot笔记(二)——对象创建

对象的创建

  • 前言
  • new关键字
  • Java为什么可以跨平台
  • Zero字节码解释器

前言

类加载到系统之后,我们需要使用它的时候,构建对象。如何构建对象
HotSpot笔记(二)——对象创建_第1张图片

new关键字

我们要使用一个类的对象,就需要先创建它的对象,创建有五种方式,但是我们最常用的是new。

DemoApplication demo = new DemoApplication();
//demo对象创建的字节码
0: new           #10  // class com/bean/anotation/ownanotation/DemoApplication
3: dup
4: invokespecial #15                 // Method "":()V
7: astore_1

Java为什么可以跨平台

java在编译期没有直接编译成机器码(各平台汇编语言不同),而是字节码,字节码由JVM提供,所以只要安装了对应平台的jdk,都可以运行同一个java系统软件。一处编写,多处运行。这个跨平台由JVM实现,它为不同平台编写了不同的汇编模板解释器来解释字节码。
HotSpot笔记(二)——对象创建_第2张图片
JVM有两种解释器:

  1. Zero字节码解释器,一种是基于switch-and-dispatch,也就是我们常用的switch语句对256条字节码指令进行解析。但很低效
  2. 汇编模板解释器,字节码指令直接对应汇编指令语句,不就是当前可实现的最快速度么。也正是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);
      }

你可能感兴趣的:(jvm,java,开发语言)