`
xieyj
  • 浏览: 99911 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

java解释器的阅读

阅读更多

     前面已经提到了java的方法入口是Interpreter::entry_for_method,此处就将cpu控制权交给了java的解释器。

上面的entry_for_method为这个AbstractInterpreterGenerator::generate_method_entry函数的返回值,在此还是以X86机器为例,普通的方法由InterpreterGenerator::generate_normal_entry返回。

     address InterpreterGenerator::generate_normal_entry(bool synchronized) {

                .......

          //调用真正解释器的地方

          RuntimeAddress normal(CAST_FROM_FN_PTR(address, BytecodeInterpreter::run));
           RuntimeAddress checking(CAST_FROM_FN_PTR(address, BytecodeInterpreter::runWithChecks));

           __ call(JvmtiExport::can_post_interpreter_events() ? checking : normal);
           __ popl(rax);                                                  // discard parameter to run

     }

   在执行到上面的call时,就会调用了BytecodeInterpreter::run方法。此方法在BytecodeInterpreter.cpp里面,用#ifdef这些包含,不容易找到。这也是一个硕大的方法。挑选进行字节码解释部分分析一下。

     while (1){

            opcode = *pc;

            switch (opcode){

                   ...........

                   CASE(_new): {
                           u2 index = Bytes::get_Java_u2(pc+1);
                           constantPoolOop constants = istate->method()->constants();
                           if (!constants->tag_at(index).is_unresolved_klass()) {
                            // Make sure klass is initialized and doesn't have a finalizer
                           oop entry = (klassOop) *constants->obj_at_addr(index);
                           assert(entry->is_klass(), "Should be resolved klass");
                           klassOop k_entry = (klassOop) entry;
                           assert(k_entry->klass_part()->oop_is_instance(), "Should be instanceKlass");
                           instanceKlass* ik = (instanceKlass*) k_entry->klass_part();
                           if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {
                           size_t obj_size = ik->size_helper();
                           oop result = NULL;
                           // If the TLAB isn't pre-zeroed then we'll have to do it
                           bool need_zero = !ZeroTLAB;
                           if (UseTLAB) {
                                   result = (oop) THREAD->tlab().allocate(obj_size);
                           }
                           if (result == NULL) {
                                   need_zero = true;
                                   // Try allocate in shared eden
                           retry:
                                   HeapWord* compare_to = *Universe::heap()->top_addr();
                                   HeapWord* new_top = compare_to + obj_size;
                                   if (new_top <= *Universe::heap()->end_addr()) {
                                               if (Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) {
                                               goto retry;
                                 }
                           result = (oop) compare_to;
                       }
                     }
                  if (result != NULL) {
                            // Initialize object (if nonzero size and need) and then the header
                        if (need_zero ) {
                                  HeapWord* to_zero = (HeapWord*) result + sizeof(oopDesc) / oopSize;
                                  obj_size -= sizeof(oopDesc) / oopSize;
                                  if (obj_size > 0 ) {
                                          memset(to_zero, 0, obj_size * HeapWordSize);
                                  }
                   }
                   if (UseBiasedLocking) {
                             result->set_mark(ik->prototype_header());
                   } else {
                            result->set_mark(markOopDesc::prototype());
                   }
                   result->set_klass(k_entry);
                   SET_STACK_OBJECT(result, 0);
                   UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
                 }
              }
          }
          // Slow case allocation
          CALL_VM(InterpreterRuntime::_new(THREAD, METHOD->constants(), index),
                handle_exception);
          SET_STACK_OBJECT(THREAD->vm_result(), 0);
          THREAD->set_vm_result(NULL);
          UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);
      }

   //上面挑选一段new字节码的解释过程,整个run函数用到太多的宏,看起来太费劲,个人感觉宏难以理解,还是少用为好

      ................

      if (!THREAD->has_pending_exception()) {
        CONTINUE;
      }
      /* We will be gcsafe soon, so flush our state. */
      DECACHE_PC();
      goto handle_exception;
    }
  do_continue: ;

 }

 .........

 //下面是些处理异常的操作

由上面的代码可以看到,整个解释过程就是不断读入字节码,和系统预先定义好的字节码进行匹配(也就是上面的case处理)的过程。解释所用到的java栈、栈桢、本地方法栈等,还有待于慢慢阅读分析。

 

1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics