`
lobin
  • 浏览: 417536 次
  • 性别: 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
分享到:
评论

相关推荐

    jdk,jvm源码

    Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。JDK(Java Development Kit)包含了开发和运行Java程序所需的所有工具,包括JVM。当我们谈论"jdk,jvm...

    推荐一些JVM原理,JVM调优,JVM内存模型,JAVA并发 电子书1

    标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...

    jvm 详细介绍,了解jvm各个组成部分和功能

    ### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心在于源文件的编译与执行。不同于 C/C++ 这类需要针对不同平台进行编译的语言,Java 采用了一种更为灵活的...

    JVM中文指令手册.pdf

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

    深入JVM内核—原理、诊断与优化视频教程-3.常用JVM配置参数

    在Java开发领域,JVM(Java Virtual Machine)是运行所有Java程序的核心,它负责解析字节码并执行程序。深入理解JVM的内核原理、诊断技巧以及优化方法对于提升应用性能至关重要。本教程——“深入JVM内核—原理、...

    JVM必知必会

    ### JVM必知必会知识点梳理 #### 1. JVM的定义与层次 Java虚拟机(JVM)具有多重含义: - **一套规范**:即Java虚拟机规范,定义了Java虚拟机应该具有的行为。 - **一种实现**:例如HotSpot、J9、JRockit,它们都是...

    JVM入门实战/arthas实战/垃圾回收算法/垃圾回收器/jvm内存模型分析

    本系列课程从JVM基础到高级实战,老师手把手教你如何进行JVM调优,思路清晰,没有废话,旨在挑战高薪。 课程亮点: 1、基于阿里arthas进行JVM调优; 2、基于代码排查OOM问题,拒绝空讲; 3、总结JVM通用的调优思路;...

    深入JVM内核—原理、诊断与优化

    《深入JVM内核—原理、诊断与优化》是一份深度探索Java虚拟机(JVM)的视频教程,旨在帮助开发者全面理解JVM的工作机制,掌握性能诊断技巧,并能进行有效的优化。本教程覆盖了从基础到高级的JVM主题,不仅适用于Java...

    jvm crash的崩溃日志详细分析及注意点

    JVM(Java Virtual Machine)是Java程序运行的核心组件,它负责解释和执行字节码。然而,当JVM出现严重错误或无法恢复的问题时,它可能会崩溃并生成一个崩溃日志,这通常被称为`hs_err_pid.log`文件。这篇内容将深入...

    R大(国内JVM权威)资料合集

    R大作为国内JVM领域的权威专家,分享了一系列与JVM相关的知识点,涉及高级语言虚拟机的基础概念、重要书籍推荐、编译器设计与优化等多个方面。这些内容不仅对初学者友好,也为专业人士提供了深入理解JVM机制的机会。...

    jvm指令手册 +JVM必知必会,掌握虚拟机编译过程.rar

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 引入Java语言虚拟机后,Java语言在不同平台...

    狂神说JVM探究.rar

    【狂神说JVM探究】是一份集合了多种格式的学习资料,主要涵盖了Java虚拟机(JVM)的基础知识。这份资料出自B站上的【狂神说Java】系列教程,为快速入门JVM提供了详实的笔记。以下是根据这些资源可能包含的一些关键...

    idea插件JVM内存工具JProfiler11

    5. **JVM配置调整**:JProfiler11还可以提供JVM参数建议,帮助开发者正确设置JVM初始堆大小、最大堆大小、内存池等关键参数,确保应用程序稳定运行。 在实际使用中,JProfiler11的详细报告和可视化界面使得问题定位...

    JVM图解-JVM指令-JVM原型图.rar

    在这个压缩包中,"JVM图解.png"可能是对JVM内部结构的可视化表示,"JVM图解"可能是一个详细的文档,解释了JVM的工作原理,而"JVM指令手册 中文版"则提供了JVM可执行的所有指令的详细信息。下面,我们将深入探讨JVM的...

    JAVA虚拟机(JVM)规范(中文版).rar

    **JAVA虚拟机(JVM)规范** JAVA虚拟机(JVM)是Java语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能在任何支持JVM的平台上运行,实现了“一次编写,到处运行”的目标。JVM规范定义了Java程序如何...

    jvm 启动过程 JVM 原理

    Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。本文将深入探讨JVM的启动过程及其基本原理。 首先,我们需要理解JVM的基本概念。JVM是Java Virtual Machine的缩写,它是...

    SAP JVM 4.1 64 bits

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

    马士兵jvm调优笔记.docx

    ### 马士兵JVM调优笔记知识点梳理 #### 一、Java内存结构 Java程序运行时,其内存被划分为几个不同的区域,包括堆内存(Heap)、方法区(Method Area)、栈(Stack)、程序计数器(Program Counter Register)以及...

    jvm 配置jvm参数

    ### JVM参数配置详解 #### 一、理解JVM参数配置的重要性 Java Virtual Machine (JVM) 是运行Java程序的核心环境,其性能优化很大程度上依赖于正确的JVM参数配置。合理配置JVM参数不仅可以显著提升应用程序的运行...

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

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

Global site tag (gtag.js) - Google Analytics