`
lobin
  • 浏览: 433164 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

 

编译阶段

Java的编译包括java文件的源代码的编译和中间字节码的运行时解释编译。

 

java文件的源代码的编译是通过Java实现的,不在JVM实现,之所以将java文件的源代码的编译也放在这篇文章,主要是将java完整的编译过程都放在一起。

 

Java源代码编译参考sun.tools.javac.SourceClass#compileClass代码,源代码位于jdk\src\share\classes\sun\tools\javac\SourceClass.java。入口在sun.tools.javac.Main#main,源代码位于jdk\src\share\classes\sun\tools\javac\Main.java

 

Java源代码文件编译期间的词法分析、语法分析、语义分析包括中间字节码class文件生成以及部分编译阶段的优化阶段是在一起的。

 

词法分析

参考sun.tools.java.Parser#parseFile代码,源代码位置位于jdk\src\share\classes\sun\tools\javac\BatchParser.java

 

语法分析

 

抽象语法树

 

 

字节码

Java字节码(class)文件结构解析,参考文档:https://lobin.iteye.com/blog/2438472

 

从Java源代码到字节码class文件的编译过程参考:编译阶段。

 

Java对象创建

下面是创建一个HashMap对象(new HashMap<String, Object>(initialCapacity, loadFactor);对应的字节码

       0: new           #2                  // class java/util/HashMap
       3: dup
       4: iload_1
       5: fload_2
       6: invokespecial #3                  // Method java/util/HashMap."<init>":(IF)V

 

 

if (true) {
    System.out.println("1");
} else {
    System.out.println("0");
}
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String 1
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V

 

 

java方法编译后的字节码:

参考hotspot\src\share\vm\shark\sharkCompiler.hpp

// Compile a normal (bytecode) method and install it in the VM
void compile_method(ciEnv* env, ciMethod* target, int entry_bci);

 

void SharkCompiler::compile_method(ciEnv*    env,
                                   ciMethod* target,
                                   int       entry_bci) {
  assert(is_initialized(), "should be");
  ResourceMark rm;
  const char *name = methodname(
    target->holder()->name()->as_utf8(), target->name()->as_utf8());

  // Do the typeflow analysis
  ciTypeFlow *flow;
  if (entry_bci == InvocationEntryBci)
    flow = target->get_flow_analysis();
  else
    flow = target->get_osr_flow_analysis(entry_bci);
  if (flow->failing())
    return;
  if (SharkPrintTypeflowOf != NULL) {
    if (!fnmatch(SharkPrintTypeflowOf, name, 0))
      flow->print_on(tty);
  }

  // Create the recorders
  Arena arena;
  env->set_oop_recorder(new OopRecorder(&arena));
  OopMapSet oopmaps;
  env->set_debug_info(new DebugInformationRecorder(env->oop_recorder()));
  env->debug_info()->set_oopmaps(&oopmaps);
  env->set_dependencies(new Dependencies(env));

  // Create the code buffer and builder
  CodeBuffer hscb("Shark", 256 * K, 64 * K);
  hscb.initialize_oop_recorder(env->oop_recorder());
  MacroAssembler *masm = new MacroAssembler(&hscb);
  SharkCodeBuffer cb(masm);
  SharkBuilder builder(&cb);

  // Emit the entry point
  SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry));

  // Build the LLVM IR for the method
  Function *function = SharkFunction::build(env, &builder, flow, name);

  // Generate native code.  It's unpleasant that we have to drop into
  // the VM to do this -- it blocks safepoints -- but I can't see any
  // other way to handle the locking.
  {
    ThreadInVMfromNative tiv(JavaThread::current());
    generate_native_code(entry, function, name);
  }

  // Install the method into the VM
  CodeOffsets offsets;
  offsets.set_value(CodeOffsets::Deopt, 0);
  offsets.set_value(CodeOffsets::Exceptions, 0);
  offsets.set_value(CodeOffsets::Verified_Entry,
                    target->is_static() ? 0 : wordSize);

  ExceptionHandlerTable handler_table;
  ImplicitExceptionTable inc_table;

  env->register_method(target,
                       entry_bci,
                       &offsets,
                       0,
                       &hscb,
                       0,
                       &oopmaps,
                       &handler_table,
                       &inc_table,
                       this,
                       env->comp_level(),
                       false,
                       false);
}

 

JVM

在阅读jvm代码的时候经常会碰到TRAPS,THREAD。出现TRAPS的地方都在方法声明的参数后面,同时出现TRAPS的地方基本都会出现THREAD。如:

klassOop allocate_instance_klass(Symbol* name,

                                   int vtable_len,

                                   int itable_len,

                                   int static_field_size,

                                   unsigned int nonstatic_oop_map_count,

                                   ReferenceType rt,

 

                                   TRAPS);

 

TRAPS,THREAD是两个宏,在hotspot\src\share\vm\utilities\exceptions.hpp中是这样定义的

#define THREAD __the_thread__

#define TRAPS  Thread* THREAD

TRAPS出现在方法声明的参数后面表示方法最后一个参数Thread* __the_thread__,如上面的函数声明展开后:

klassOop allocate_instance_klass(Symbol* name,

                                   int vtable_len,

                                   int itable_len,

                                   int static_field_size,

                                   unsigned int nonstatic_oop_map_count,

                                   ReferenceType rt,

 

                                   Thread* __the_thread__);

对应的THREAD表示对应函数的最后一个变量__the_thread__。

 

参考另一篇文章:https://lobin.iteye.com/blog/2327905

 

Class类加载机制

 
hotspot\src\share\vm\prims\jvm.cpp
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init,
                                    Handle loader, Handle protection_domain,
                                    jboolean throwError, TRAPS) {
  // Security Note:
  //   The Java level wrapper will perform the necessary security check allowing
  //   us to pass the NULL as the initiating class loader.  The VM is responsible for
  //   the checkPackageAccess relative to the initiating class loader via the
  //   protection_domain. The protection_domain is passed as NULL by the java code
  //   if there is no security manager in 3-arg Class.forName().
  klassOop klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL);

  KlassHandle klass_handle(THREAD, klass);
  // Check if we should initialize the class
  if (init && klass_handle->oop_is_instance()) {
    klass_handle->initialize(CHECK_NULL);
  }
  return (jclass) JNIHandles::make_local(env, klass_handle->java_mirror());
}
 这段代码中主要逻辑就是resolve_or_fail,initialize,make_local。
 
 
 

字节码

参考另一篇文章:https://lobin.iteye.com/blog/2440503

 

Java内存模型

参考另一篇文章:https://lobin.iteye.com/blog/2325729

 
 

 JVM Stack

 



 

 

Stack

参考SharkStack类,代码:hotspot\src\share\vm\shark\sharkStack.hpp

 

栈帧

每个方法调用都对应一个栈帧(frame )。包含本地变量表,操作栈(operand stack),当前调用的方法对应类的运行时常量池(run-time constant pool)的引用(reference)。

https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6 写道
A frame may be extended with additional implementation-specific information, such as debugging information.

 

本地变量表使用一个数组保存每一个本地变量(local variable)。

本地变量表和操作栈 的大小在编译期就已确定。

 

本地变量表

 

操作栈 

 

参考SharkState类,代码:hotspot\src\share\vm\shark\sharkState.hpp

 

参考代码:hotspot\src\share\vm\shark\sharkStateScanner.cpp

 

void SharkStateScanner::scan(SharkState* state) {
  start_frame();

  // Expression stack
  stack_integrity_checks(state);
  start_stack(state->stack_depth());
  for (int i = state->stack_depth() - 1; i >= 0; i--) {
    process_stack_slot(
      i,
      state->stack_addr(i),
      stack()->stack_slots_offset() +
        i + max_stack() - state->stack_depth());
  }
  end_stack();

  // Monitors
  start_monitors(state->num_monitors());
  for (int i = 0; i < state->num_monitors(); i++) {
    process_monitor(
      i,
      stack()->monitor_offset(i),
      stack()->monitor_object_offset(i));
  }
  end_monitors();

  // Frame header
  start_frame_header();
  process_oop_tmp_slot(
    state->oop_tmp_addr(), stack()->oop_tmp_slot_offset());
  process_method_slot(state->method_addr(), stack()->method_slot_offset());
  process_pc_slot(stack()->pc_slot_offset());
  end_frame_header();

  // Local variables
  locals_integrity_checks(state);
  start_locals();
  for (int i = 0; i < max_locals(); i++) {
    process_local_slot(
      i,
      state->local_addr(i),
      stack()->locals_slots_offset() + max_locals() - 1 - i);
  }
  end_locals();

  end_frame();
}

 

 

 

 

public static void main(String[] args) {
	apply(1);
}

private static void apply(int arg) {
	int argc = arg;
	try {
		apply(++arg);
	} catch(Throwable e) {
		System.out.println(argc);
		System.out.println(e);
	}
}

 

5617
java.lang.StackOverflowError

 

 将System.out.println(e);改成e.printStackTrace();打印出栈信息:

5617
java.lang.StackOverflowError
	at sparktest.StackTest.apply(StackTest.java:14)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
	at sparktest.StackTest.apply(StackTest.java:12)
...

 

java call

java call包括special,virtual,Static方法调用。这些方法调用都会调用到Low-level的call函数:

static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);

 

另外还有一个call_helper方法:

static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);

上面的Low-level的call函数通过java_call_t的函数指针调用call_helper函数。

 

java_call_t

java_call_t被定义成一个函数指针,用来表示java调用。如调用java的方法,包括virtual方法调用,特定(special)方法调用,静态(static)方法调用。

其中virtual方法,特定(special)方法都是普通的非静态方法。这里的virtual方法,特定(special)方法,静态(static)方法就是java代码编译成字节码后方法调用的地方常见的invokespecial,invokevirtual,invokestatic指令。这些指令参考另一篇文章:https://lobin.iteye.com/blog/2440503

 

 

typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);

 

java call(special)

 

  // call_special
  // ------------
  // The receiver must be first oop in argument list
  static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);

  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args
  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 

 

 

java call(virtual)

 

  // virtual call
  // ------------

  // The receiver must be first oop in argument list
  static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);

  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args
  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 

 

 

java call(Static)

 

  // Static call
  // -----------
  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);

  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 

 

 

call_helper函数将java call封装成JavaCallWrapper,然后通过一个调用代理CallStub(调用StubRoutines::call_stub()函数得到这个CallStub调用代理

 

调用代理(CallStub

 

StubRoutines::call_stub()函数:

static CallStub call_stub()                              { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }

 

其中:

#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value)))

 

展开后:

static CallStub call_stub()                              { return ((CallStub)(castable_address(_call_stub_entry)));}

 

_call_stub_entry由StubGenerator extends StubCodeGenerator初始化,参考generate_call_stub函数,它返回的是调用代理的第一条指令的地址(address),也就是在调用这个调用代理时要跳转到的目标地址,以及调用这个调用代理后要跳转返回的地址,为调用代理(这个调用代理可以理解为一段汇编指令程序,负责代理调用方法)建栈(见__ enter();...__ pop(rbp);),传递参数,方法调用时call指令要跳转到的目标地址。

 

在看JVM在实现汇编指令等价函数操作时,和汇编指令语法一样,也有它的汇编风格,参考AT&T汇编风格。

 

 

调用代理(CallStub)也是一个函数指针

 

  // Calls to Java

  typedef void (*CallStub)(

    address   link,

    intptr_t* result,

    BasicType result_type,

    methodOopDesc* method,

    address   entry_point,

    intptr_t* parameters,

    int       size_of_parameters,

    TRAPS

  );

 

 

 

 

 

jmethodID -> methodHandle -> JavaCalls::call -> StubRoutines::call_stub -> CallStub -> 

 

CallStub

64位x86 CPU实现:generate_call_stub

参考src\cpu\x86\vm\stubGenerator_x86_64.cpp

address generate_call_stub(address& return_address) {
  assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 &&
         (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off,
         "adjust this code");
  StubCodeMark mark(this, "StubRoutines", "call_stub");
  address start = __ pc();

  // same as in generate_catch_exception()!
  const Address rsp_after_call(rbp, rsp_after_call_off * wordSize);

  const Address call_wrapper  (rbp, call_wrapper_off   * wordSize);
  const Address result        (rbp, result_off         * wordSize);
  const Address result_type   (rbp, result_type_off    * wordSize);
  const Address method        (rbp, method_off         * wordSize);
  const Address entry_point   (rbp, entry_point_off    * wordSize);
  const Address parameters    (rbp, parameters_off     * wordSize);
  const Address parameter_size(rbp, parameter_size_off * wordSize);

  // same as in generate_catch_exception()!
  const Address thread        (rbp, thread_off         * wordSize);

  const Address r15_save(rbp, r15_off * wordSize);
  const Address r14_save(rbp, r14_off * wordSize);
  const Address r13_save(rbp, r13_off * wordSize);
  const Address r12_save(rbp, r12_off * wordSize);
  const Address rbx_save(rbp, rbx_off * wordSize);

  // stub code
  __ enter();
  __ subptr(rsp, -rsp_after_call_off * wordSize);

  // save register parameters
#ifndef _WIN64
  __ movptr(parameters,   c_rarg5); // parameters
  __ movptr(entry_point,  c_rarg4); // entry_point
#endif

  __ movptr(method,       c_rarg3); // method
  __ movl(result_type,  c_rarg2);   // result type
  __ movptr(result,       c_rarg1); // result
  __ movptr(call_wrapper, c_rarg0); // call wrapper

  // save regs belonging to calling function
  __ movptr(rbx_save, rbx);
  __ movptr(r12_save, r12);
  __ movptr(r13_save, r13);
  __ movptr(r14_save, r14);
  __ movptr(r15_save, r15);
#ifdef _WIN64
  for (int i = 6; i <= 15; i++) {
    __ movdqu(xmm_save(i), as_XMMRegister(i));
  }

  const Address rdi_save(rbp, rdi_off * wordSize);
  const Address rsi_save(rbp, rsi_off * wordSize);

  __ movptr(rsi_save, rsi);
  __ movptr(rdi_save, rdi);
#else
  const Address mxcsr_save(rbp, mxcsr_off * wordSize);
  {
    Label skip_ldmx;
    __ stmxcsr(mxcsr_save);
    __ movl(rax, mxcsr_save);
    __ andl(rax, MXCSR_MASK);    // Only check control and mask bits
    ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std());
    __ cmp32(rax, mxcsr_std);
    __ jcc(Assembler::equal, skip_ldmx);
    __ ldmxcsr(mxcsr_std);
    __ bind(skip_ldmx);
  }
#endif

  // Load up thread register
  __ movptr(r15_thread, thread);
  __ reinit_heapbase();

#ifdef ASSERT
  // make sure we have no pending exceptions
  {
    Label L;
    __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
    __ jcc(Assembler::equal, L);
    __ stop("StubRoutines::call_stub: entered with pending exception");
    __ bind(L);
  }
#endif

  // pass parameters if any
  BLOCK_COMMENT("pass parameters if any");
  Label parameters_done;
  __ movl(c_rarg3, parameter_size);
  __ testl(c_rarg3, c_rarg3);
  __ jcc(Assembler::zero, parameters_done);

  Label loop;
  __ movptr(c_rarg2, parameters);       // parameter pointer
  __ movl(c_rarg1, c_rarg3);            // parameter counter is in c_rarg1
  __ BIND(loop);
  __ movptr(rax, Address(c_rarg2, 0));// get parameter
  __ addptr(c_rarg2, wordSize);       // advance to next parameter
  __ decrementl(c_rarg1);             // decrement counter
  __ push(rax);                       // pass parameter
  __ jcc(Assembler::notZero, loop);

  // call Java function
  __ BIND(parameters_done);
  __ movptr(rbx, method);             // get methodOop
  __ movptr(c_rarg1, entry_point);    // get entry_point
  __ mov(r13, rsp);                   // set sender sp
  BLOCK_COMMENT("call Java function");
  __ call(c_rarg1);

  BLOCK_COMMENT("call_stub_return_address:");
  return_address = __ pc();

  // store result depending on type (everything that is not
  // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
  __ movptr(c_rarg0, result);
  Label is_long, is_float, is_double, exit;
  __ movl(c_rarg1, result_type);
  __ cmpl(c_rarg1, T_OBJECT);
  __ jcc(Assembler::equal, is_long);
  __ cmpl(c_rarg1, T_LONG);
  __ jcc(Assembler::equal, is_long);
  __ cmpl(c_rarg1, T_FLOAT);
  __ jcc(Assembler::equal, is_float);
  __ cmpl(c_rarg1, T_DOUBLE);
  __ jcc(Assembler::equal, is_double);

  // handle T_INT case
  __ movl(Address(c_rarg0, 0), rax);

  __ BIND(exit);

  // pop parameters
  __ lea(rsp, rsp_after_call);

#ifdef ASSERT
  // verify that threads correspond
  {
    Label L, S;
    __ cmpptr(r15_thread, thread);
    __ jcc(Assembler::notEqual, S);
    __ get_thread(rbx);
    __ cmpptr(r15_thread, rbx);
    __ jcc(Assembler::equal, L);
    __ bind(S);
    __ jcc(Assembler::equal, L);
    __ stop("StubRoutines::call_stub: threads must correspond");
    __ bind(L);
  }
#endif

  // restore regs belonging to calling function
#ifdef _WIN64
  for (int i = 15; i >= 6; i--) {
    __ movdqu(as_XMMRegister(i), xmm_save(i));
  }
#endif
  __ movptr(r15, r15_save);
  __ movptr(r14, r14_save);
  __ movptr(r13, r13_save);
  __ movptr(r12, r12_save);
  __ movptr(rbx, rbx_save);

#ifdef _WIN64
  __ movptr(rdi, rdi_save);
  __ movptr(rsi, rsi_save);
#else
  __ ldmxcsr(mxcsr_save);
#endif

  // restore rsp
  __ addptr(rsp, -rsp_after_call_off * wordSize);

  // return
  __ pop(rbp);
  __ ret(0);

  // handle return types different from T_INT
  __ BIND(is_long);
  __ movq(Address(c_rarg0, 0), rax);
  __ jmp(exit);

  __ BIND(is_float);
  __ movflt(Address(c_rarg0, 0), xmm0);
  __ jmp(exit);

  __ BIND(is_double);
  __ movdbl(Address(c_rarg0, 0), xmm0);
  __ jmp(exit);

  return start;
}

 

Assembler

MacroAssembler -》Assembler -》AbstractAssembler

 

AbstractAssembler:

hotspot\src\share\vm\asm\assembler.hpp

 

x86:

MacroAssembler:

hotspot\src\cpu\x86\vm\assembler_x86.hpp

 

Assembler:

hotspot\src\cpu\x86\vm\assembler_x86.hpp

 

sparc:

 

AbstractAssembler声明如下:

  // Instruction boundaries (required when emitting relocatable values).
  class InstructionMark: public StackObj {
   private:
    AbstractAssembler* _assm;

   public:
    InstructionMark(AbstractAssembler* assm) : _assm(assm) {
      assert(assm->inst_mark() == NULL, "overlapping instructions");
      _assm->set_inst_mark();
    }
    ~InstructionMark() {
      _assm->clear_inst_mark();
    }
  };
  friend class InstructionMark;
  #ifdef ASSERT
  // Make it return true on platforms which need to verify
  // instruction boundaries for some operations.
  inline static bool pd_check_instruction_mark();

  // Add delta to short branch distance to verify that it still fit into imm8.
  int _short_branch_delta;

  int  short_branch_delta() const { return _short_branch_delta; }
  void set_short_branch_delta()   { _short_branch_delta = 32; }
  void clear_short_branch_delta() { _short_branch_delta = 0; }

  class ShortBranchVerifier: public StackObj {
   private:
    AbstractAssembler* _assm;

   public:
    ShortBranchVerifier(AbstractAssembler* assm) : _assm(assm) {
      assert(assm->short_branch_delta() == 0, "overlapping instructions");
      _assm->set_short_branch_delta();
    }
    ~ShortBranchVerifier() {
      _assm->clear_short_branch_delta();
    }
  };
  #else
  // Dummy in product.
  class ShortBranchVerifier: public StackObj {
   public:
    ShortBranchVerifier(AbstractAssembler* assm) {}
  };
  #endif

  // Label functions
  void print(Label& L);

 public:

  // Creation
  AbstractAssembler(CodeBuffer* code);

  // save end pointer back to code buf.
  void sync();

  // ensure buf contains all code (call this before using/copying the code)
  void flush();

  // min and max values for signed immediate ranges
  static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1))    ; }
  static int max_simm(int nbits) { return  (intptr_t(1) << (nbits - 1)) - 1; }

  // Define some:
  static int min_simm10() { return min_simm(10); }
  static int min_simm13() { return min_simm(13); }
  static int min_simm16() { return min_simm(16); }

  // Test if x is within signed immediate range for nbits
  static bool is_simm(intptr_t x, int nbits) { return min_simm(nbits) <= x && x <= max_simm(nbits); }

  // Define some:
  static bool is_simm5( intptr_t x) { return is_simm(x, 5 ); }
  static bool is_simm8( intptr_t x) { return is_simm(x, 8 ); }
  static bool is_simm10(intptr_t x) { return is_simm(x, 10); }
  static bool is_simm11(intptr_t x) { return is_simm(x, 11); }
  static bool is_simm12(intptr_t x) { return is_simm(x, 12); }
  static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
  static bool is_simm16(intptr_t x) { return is_simm(x, 16); }
  static bool is_simm26(intptr_t x) { return is_simm(x, 26); }
  static bool is_simm32(intptr_t x) { return is_simm(x, 32); }

  // Accessors
  CodeBuffer*   code() const;          // _code_section->outer()
  CodeSection*  code_section() const   { return _code_section; }
  int           sect() const;          // return _code_section->index()
  address       pc() const             { return _code_pos; }
  int           offset() const         { return _code_pos - _code_begin; }
  int           locator() const;       // CodeBuffer::locator(offset(), sect())
  OopRecorder*  oop_recorder() const   { return _oop_recorder; }
  void      set_oop_recorder(OopRecorder* r) { _oop_recorder = r; }

  address  inst_mark() const;
  void set_inst_mark();
  void clear_inst_mark();

  // Constants in code
  void a_byte(int x);
  void a_long(jint x);
  void relocate(RelocationHolder const& rspec, int format = 0);
  void relocate(   relocInfo::relocType rtype, int format = 0) {
    if (rtype != relocInfo::none)
      relocate(Relocation::spec_simple(rtype), format);
  }

  static int code_fill_byte();         // used to pad out odd-sized code buffers

  // Associate a comment with the current offset.  It will be printed
  // along with the disassembly when printing nmethods.  Currently
  // only supported in the instruction section of the code buffer.
  void block_comment(const char* comment);

  // Label functions
  void bind(Label& L); // binds an unbound label L to the current code position

  // Move to a different section in the same code buffer.
  void set_code_section(CodeSection* cs);

  // Inform assembler when generating stub code and relocation info
  address    start_a_stub(int required_space);
  void       end_a_stub();
  // Ditto for constants.
  address    start_a_const(int required_space, int required_align = sizeof(double));
  void       end_a_const();

  // constants support
  address long_constant(jlong c) {
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      *(jlong*)ptr = c;
      _code_pos = ptr + sizeof(c);
      end_a_const();
    }
    return ptr;
  }
  address double_constant(jdouble c) {
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      *(jdouble*)ptr = c;
      _code_pos = ptr + sizeof(c);
      end_a_const();
    }
    return ptr;
  }
  address float_constant(jfloat c) {
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      *(jfloat*)ptr = c;
      _code_pos = ptr + sizeof(c);
      end_a_const();
    }
    return ptr;
  }
  address address_constant(address c) {
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      *(address*)ptr = c;
      _code_pos = ptr + sizeof(c);
      end_a_const();
    }
    return ptr;
  }
  address address_constant(address c, RelocationHolder const& rspec) {
    address ptr = start_a_const(sizeof(c), sizeof(c));
    if (ptr != NULL) {
      relocate(rspec);
      *(address*)ptr = c;
      _code_pos = ptr + sizeof(c);
      end_a_const();
    }
    return ptr;
  }

  // Bootstrapping aid to cope with delayed determination of constants.
  // Returns a static address which will eventually contain the constant.
  // The value zero (NULL) stands instead of a constant which is still uncomputed.
  // Thus, the eventual value of the constant must not be zero.
  // This is fine, since this is designed for embedding object field
  // offsets in code which must be generated before the object class is loaded.
  // Field offsets are never zero, since an object's header (mark word)
  // is located at offset zero.
  RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) {
    return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
  }
  RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) {
    return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset);
  }
  virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
  // Last overloading is platform-dependent; look in assembler_<arch>.cpp.
  static intptr_t* delayed_value_addr(int(*constant_fn)());
  static intptr_t* delayed_value_addr(address(*constant_fn)());
  static void update_delayed_values();

  // Bang stack to trigger StackOverflowError at a safe location
  // implementation delegates to machine-specific bang_stack_with_offset
  void generate_stack_overflow_check( int frame_size_in_bytes );
  virtual void bang_stack_with_offset(int offset) = 0;


  /**
   * A platform-dependent method to patch a jump instruction that refers
   * to this label.
   *
   * @param branch the location of the instruction to patch
   * @param masm the assembler which generated the branch
   */
  void pd_patch_instruction(address branch, address target);

#ifndef PRODUCT
  /**
   * Platform-dependent method of printing an instruction that needs to be
   * patched.
   *
   * @param branch the instruction to be patched in the buffer.
   */
  static void pd_print_patched_instruction(address branch);
#endif // PRODUCT
};

 

 

 

 

JVM 处理器体系

参考文档:https://lobin.iteye.com/blog/2438471

 

x86

寄存器:

Register rax

rcx

rdx

rbx

rsp

rbp

rsi

rdi

r8

r9

r10

r11

r12

r13

r14

r15

XMMRegister xmm0

xmm1

xmm2

xmm3

xmm4

xmm5

xmm6

xmm7

xmm8

xmm9

xmm10

xmm11

xmm12

xmm13

xmm14

xmm15

MMXRegister mmx0

mmx1

mmx2

mmx3

mmx4

mmx5

mmx6

mmx7

 

源代码参考如下定义:

#define CONSTANT_REGISTER_DECLARATION(type, name, value) \

extern const type name;                                  \

enum { name##_##type##EnumValue = (value) }

 

以Register rbp为例,

CONSTANT_REGISTER_DECLARATION(Register, rbp,    (5));

预处理阶段展开后:

extern const Register rbp;

enum { rbp_RegisterEnumValue = (5) } ;

 

 

PC程序计数器

 

 

GC

 


 
 

 

 

 

Java Debug调试工具:jdb

>javac -g StackTest.java

>jdb StackTest

> stop at StackTest:6

> run

print StackTest.arg

stop at StackTest:10

list

threads

cont

where 0x1

 

Java:构建发布JRE&JDK版本:1.6 

参考另一篇文章:https://lobin.iteye.com/blog/620153

 

1、https://www.oracle.com/technetwork/java/javase/tech/index.html

2、http://openjdk.java.net/projects/mlvm/jvmlangsummit/

3、https://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf

4、https://download.java.net/openjdk/jdk6

 

5、http://hg.openjdk.java.net/jdk/jdk/raw-file/tip/doc/building.html

6、http://hg.openjdk.java.net/jdk6/jdk6/raw-file/tip/README-builds.html

 

7、https://docs.oracle.com/javase/specs/jvms/se8/html/index.html

8、The Java Memory Model, http://www.cs.umd.edu/~pugh/java/memoryModel/

9、http://groups.inf.ed.ac.uk/request/jmmexamples.pdf

10、17.4. Memory Model, https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4

11、JSR 133: JavaTM Memory Model and Thread Specification Revision, https://www.jcp.org/en/jsr/detail?id=133

 

 

 

12、https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/preface.html

13、Troubleshooting Guide for HotSpot VM, https://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/index.html

14、Java HotSpot VM Options, https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

15、https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

16、https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html

  • 大小: 42.5 KB
  • 大小: 32.9 KB
  • 大小: 38.3 KB
0
0
分享到:
评论

相关推荐

    SAP JVM 8.1 64 bits

    SAP JVM 8.1 64位是一个专为SAP系统设计的Java虚拟机,它基于Oracle的Java Development Kit (JDK) 进行优化,以满足SAP应用程序的特定需求。SAP JVM旨在提高性能、可靠性和安全性,同时确保与SAP产品的无缝集成。...

    JVM介绍

    JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一...

    SAP JVM 4.1 64 bits

    SAP JVM 4.1 64位是一个专为SAP系统设计的Java虚拟机,它主要用于运行SAP的应用程序和服务。此版本是为64位操作系统优化的,旨在提供更好的性能和内存管理能力,特别是在处理大数据量和复杂计算场景时。 首先,我们...

    JVM指令手册详细完整版.pdf

    "JVM指令手册详细完整版.pdf" 本资源是关于JVM指令的详细手册,涵盖了JVM指令的各种系列命令,包括未归类系列、const系列、push系列、ldc系列、load系列等。每个系列命令都有其特定的功能和用途,下面我们将逐一...

    JVM Specification

    Java虚拟机(JVM)是Java编程语言的核心组成部分,它为Java程序提供了运行环境。《JVM Specification》是一份详细的技术文档,详细阐述了JVM的设计、工作原理以及其与Java程序之间的交互机制。这份规范是Java开发者...

    SAP JVM 7.1 64 bits

    SAP JVM 7.1 64位是一个专为SAP系统设计的Java虚拟机,它主要用于运行SAP的应用程序和服务。这个版本是基于64位架构,这意味着它可以处理更大的内存,更适合处理大规模的企业级数据和复杂计算。下面将详细讨论SAP ...

    JVM中文指令手册.pdf

    JVM(Java Virtual Machine,Java虚拟机)是运行所有Java程序的假想计算机,是Java程序的运行环境,负责执行指令、管理数据、内存、寄存器等,是实现Java跨平台特性的关键部分。JVM指令手册详细记录了JVM的所有操作...

    JVM思维导图(包含所有JVM知识)

    Java虚拟机(JVM)是Java程序运行的基础,它提供了内存管理、类加载和执行字节码等功能。本文将深入探讨JVM的主要知识点,包括内存模型、类加载机制、垃圾收集器及其算法、内存调优工具,以及相关配置选项。 1. **...

    尚硅谷jvm整理.md

    尚硅谷jvm课件整理ppt

    JVM调优实践 ⼀、JVM调优准备⼯作 实验报告 pdf

    Java虚拟机(JVM)是Java程序运行的基础,它的调优是提高应用程序性能的关键环节。在JVM调优实践中,了解各个运行时数据区的工作原理至关重要。以下是对这些区域的详细解析: 1. **虚拟机栈**:每个线程都有一个...

    JAVA8虚拟机(jvm)规范_Chinese version.rar

    Java虚拟机(JVM)是Java程序运行的核心组件,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。《JAVA8虚拟机(jvm)规范_Chinese version》提供了关于JVM的详细中文指南,对于理解Java程序的运行...

    深入理解JVM.rar

    每个使用Java的开发者都知道Java字节码是在JRE中运行,而JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你...

    从 0 开始带你成为JVM实战高手.txt

    从零开始学习并掌握Java虚拟机(JVM)的相关知识对于任何希望深入理解Java程序运行机制的开发者来说都是一项重要技能。本篇文章将基于提供的文件标题、描述以及部分链接信息来构建一系列关于JVM的核心知识点。 ### ...

    JVM指令手册.docx

    Java虚拟机(JVM)是Java程序运行的核心组件,它负责解释执行字节码指令,为Java应用程序提供了一个跨平台的运行环境。JVM指令集是JVM内部使用的微指令集合,这些指令构成了Java字节码的基础。在《JVM指令手册》中,...

Global site tag (gtag.js) - Google Analytics