Hotspot 方法调用之StubRoutines 源码解析

  目录

一、StubRoutines

1、定义

2、  initialize1和initialize2方法

二、ResourceMark

1、ResourceArea

2、构造和析构函数

三、BufferBlob

四、CodeBlob

1、定义

2、构造和flush方法 

五、CodeBuffer

1、定义

2、构造和析构方法

3、copy_code_and_locs_to方法

六、CodeSection

1、定义

 2、initialize


上篇博客《Hotspot 方法调用之JavaCalls 源码解析》分析了本地代码调用Java方法的核心入口JavaCalls相关类的实现,本篇博客继续深入分析StubRoutines相关类的实现。

一、StubRoutines

1、定义

    StubRoutines是一个包含一系列编译程序或者JVM运行时系统使用的关键函数的地址的Holder类,其定义在hotspot src/share/vm/runtime/stubRoutines.hpp中。可以通过StubRoutines获取这些函数的内存地址,然后通过指针的方式调用目标函数,如下图:

以JavaCalls::call_helper方法中调用的StubRoutines::call_stub()方法为例说明,该方法返回的其实就是一个函数的地址,如下图:

CallStub就是这个函数的别名,这个其实是解释器执行字节码的终极入口。CAST_TO_FN_PTR宏定义就是完成指针类型转换的,如下图:

 

2、  initialize1和initialize2方法

我们重点关注StubRoutines的两个静态初始化方法initialize1和initialize2方法的实现,以此为入口了解该类的用法。这两个方法的调用链如下:

 

    最终都是在init_globals一个方法中调用的,不过initialize1在前,在universe初始化前执行,initialize2在universe初始化完成后执行,init_globals的代码如下:

  两者的源码实现说明如下:

void stubRoutines_init1() { StubRoutines::initialize1(); }
void stubRoutines_init2() { StubRoutines::initialize2(); }

void StubRoutines::initialize1() {
  if (_code1 == NULL) {
    //ResourceMark的作用类似于HandleMark,两者mark的区域不同,一个是ResourceArea,一个是HandleArea
    ResourceMark rm;
    //跟踪启动时间
    TraceTime timer("StubRoutines generation 1", TraceStartupTime);
    //创建一个保存不会重定位的本地代码的Blob
    _code1 = BufferBlob::create("StubRoutines (1)", code_size1);
    if (_code1 == NULL) {
      //创建失败抛出OOM异常
      vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)");
    }
    CodeBuffer buffer(_code1);
    //生成字节码解释模板
    StubGenerator_generate(&buffer, false);
  }
}


void StubRoutines::initialize2() {
  if (_code2 == NULL) {
    ResourceMark rm;
    TraceTime timer("StubRoutines generation 2", TraceStartupTime);
    _code2 = BufferBlob::create("StubRoutines (2)", code_size2);
    if (_code2 == NULL) {
      vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)");
    }
    CodeBuffer buffer(_code2);
    //跟initialize1中不同的是,这里传入的true,其他的都一样
    StubGenerator_generate(&buffer, true);
  }


   public:
  StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
    if (all) {
      generate_all();
    } else {
      //如果传入false执行的是initial相关的代码
      generate_initial();
    }
  }
}; // end class declaration

void StubGenerator_generate(CodeBuffer* code, bool all) {
  StubGenerator g(code, all);
}

   下面会逐一分析相关类的用法。

二、ResourceMark

      ResourceMark和HandleMark用法类似,通过构造方法来保存当前线程的ResourceArea的状态,当方法执行完毕后,通过析构函数及时释放方法执行过程中从ResourceArea中分配的内存,将当前线程的ResourceArea的状态恢复至方法执行前的状态。ResourceMark的定义位于hotspot src/share/vm/memory/resourceArea.hpp中,它定义了四个protected属性,如下:

  • _area:ResourceArea *,关联的ResourceArea实例
  • _chunk:Chunk *,_area当前使用的Chunk
  • _hwm,_max:char *,_area当前使用的Chunk的可分配内存的范围
  • _size_in_bytes:size_t,_area的总的内存大小

ResourceMark定义的核心方法就只有其构造和析构函数。可参考《Hotspot 方法调用之HandleMark 源码解析》中HandleMark和HandleArea的实现和使用方式

1、ResourceArea

    ResourceArea跟HandleArea一样继承Area,其核心就是一个方法allocate_bytes,用于分配指定大小的内存,其源码说明如下:

 ResourceArea(MEMFLAGS flags = mtThread) : Arena(flags) {
    debug_only(_nesting = 0;)
  }

  ResourceArea(size_t init_size, MEMFLAGS flags = mtThread) : Arena(flags, init_size) {
    debug_only(_nesting = 0;);
  }


char* allocate_bytes(size_t size, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
    //调用Area的Amalloc方法分配内存
    return (char*)Amalloc(size, alloc_failmode);
  }

  allocate_bytes的调用链如下:

2、构造和析构函数

     构造和析构函数的源码说明如下:

ResourceMark()               { initialize(Thread::current()); }

  ResourceMark( ResourceArea *r ) :
    _area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) {
    //保存ResourceArea的各属性
    _size_in_bytes = r->_size_in_bytes;
    debug_only(_area->_nesting++;)
    assert( _area->_nesting > 0, "must stack allocate RMs" );
  }

    void initialize(Thread *thread) {
    //保存线程thread的resource_area的各属性
    _area = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值