认识Java中的Stub与StubQueue

 更新时间:2021年09月09日 17:08:57   作者:HotSpot-Researcher  
StubQueue是用来保存生成的本地代码的Stub队列,队列每一个元素对应一个InterpreterCodelet对象,InterpreterCodelet对象继承自抽象基类Stub,下面我们介绍一下StubQueue类及相关类Stub、InterpreterCodelet类和CodeletMark类。需要的的下伙伴可以参考下面文字内容

在文章开始前先简单介绍TemplateInterpreter::initialize()函数,在这个函数中会调用TemplateTable::initialize()函数初始化模板表,随后会使用new关键字初始化定义在AbstractInterpreter类中的_code静态属性,如下:

static StubQueue* _code;

由于TemplateInterpreter继承自AbstractInterpreter,所以在TemplateInterpreter中初始化的_code属性其实就是AbstractInterpreter类中定义的_code属性。

在initialize()函数中初始化_code变量的代码如下

// InterpreterCodeSize是在平台相关
// 的templateInterpreter_x86.hpp中
// 定义的,64位下是256 * 1024
int code_size = InterpreterCodeSize;
_code = new StubQueue(
                new InterpreterCodeletInterface, 
                code_size, 
                NULL,
                "Interpreter");


StubQueue是用来保存生成的本地代码的Stub队列,队列每一个元素对应一个InterpreterCodelet对象,InterpreterCodelet对象继承自抽象基类Stub,包含了字节码对应的本地代码以及一些调试和输出信息。下面我们介绍一下StubQueue类及相关类StubInterpreterCodelet类和CodeletMark类。

1、InterpreterCodelet与Stub类

Stub类的定义如下:

class Stub VALUE_OBJ_CLASS_SPEC { ... };


InterpreterCodelet类继承自Stub类,具体的定义如下

class InterpreterCodelet: public Stub {
 private:
  int                _size;         // the size in bytes
  const char*        _description;  // a description of the codelet, for debugging & printing
  Bytecodes::Code    _bytecode;     // associated bytecode if any
 
 public:
  // Code info
  address code_begin() const  {
     return (address)this + round_to(sizeof(InterpreterCodelet), CodeEntryAlignment);
  }
  address code_end() const {
     return (address)this + size();
  }
 
  int size() const {
     return _size;
  }
  // ...
  int code_size() const { 
     return code_end() - code_begin();  
  }
  // ...
};


InterpreterCodelet实例存储在StubQueue中,每个InterpreterCodelet实例都代表一段机器指令(包含了字节码对应的机器指令片段以及一些调试和输出信息),如每个字节码都有一个InterpreterCodelet实例,所以在解释执行时,如果要执行某个字节码,则执行的就是由InterpreterCodelet实例代表的机器指令片段。

类中定义了3个属性及一些函数,其内存布局如下图所示。

 

在对齐至CodeEntryAlignment后,紧接着InterpreterCodelet的就是生成的目标代码。

2、StubQueue类

StubQueue是用来保存生成的本地机器指令片段的Stub队列,队列每一个元素都是一个InterpreterCodelet实例。

StubQueue类的定义如下:

class StubQueue: public CHeapObj<mtCode> {
 private:
  StubInterface* _stub_interface;     // the interface prototype
  address        _stub_buffer;        // where all stubs are stored
 
  int            _buffer_size;       // the buffer size in bytes
  int            _buffer_limit;      // the (byte) index of the actual buffer limit (_buffer_limit <= _buffer_size)
 
  int            _queue_begin;       // the (byte) index of the first queue entry (word-aligned)
  int            _queue_end;         // the (byte) index of the first entry after the queue (word-aligned)
 
  int            _number_of_stubs;   // the number of buffered stubs
 
 
  bool is_contiguous() const {
      return _queue_begin <= _queue_end;
  }
  int index_of(Stub* s) const {
      int i = (address)s - _stub_buffer;
      return i;
  }
  Stub* stub_at(int i) const {
      return (Stub*)(_stub_buffer + i);
  }
  Stub* current_stub() const {
      return stub_at(_queue_end);
  }
 
  // ...
}


这个类的构造函数如下:

StubQueue::StubQueue(
 StubInterface* stub_interface,  // InterpreterCodeletInterface对象
 int            buffer_size,     // 256*1024
 Mutex*         lock,
 const char*    name) : _mutex(lock)
{
  intptr_t     size = round_to(buffer_size, 2*BytesPerWord); // BytesPerWord的值为8
  BufferBlob*  blob = BufferBlob::create(name, size); // 在StubQueue中创建BufferBlob对象
 
  _stub_interface  = stub_interface;
 
  _buffer_size     = blob->content_size();
  _buffer_limit    = blob->content_size();
  _stub_buffer     = blob->content_begin();
 
  _queue_begin     = 0;
  _queue_end       = 0;
  _number_of_stubs = 0;
}


stub_interface用来保存一个InterpreterCodeletInterface类型的实例,InterpreterCodeletInterface类中定义了操作Stub的函数,避免了在Stub中定义虚函数。每个StubQueue都有一个InterpreterCodeletInterface,可以通过这个来操作StubQueue中存储的每个Stub实例。

调用BufferBlob::create()函数为StubQueue分配内存,这里我们需要记住StubQueue用的内存是通过BufferBlob分配出来的,也就是BufferBlob其本质可能是一个StubQueue。下面就来详细介绍下create()函数。

BufferBlob* BufferBlob::create(const char* name, int buffer_size) {
  // ...
  BufferBlob*    blob = NULL;
  unsigned int   size = sizeof(BufferBlob);
 
  // align the size to CodeEntryAlignment
  size = align_code_offset(size);
  size += round_to(buffer_size, oopSize); // oopSize是一个指针的宽度,在64位上就是8
 
  {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) BufferBlob(name, size);
  }
 
  return blob;
}


通过new关键字为BufferBlob分配内存,new重载运算符如下:

void* BufferBlob::operator new(size_t s, unsigned size, bool is_critical) throw() {
  void* p = CodeCache::allocate(size, is_critical);
  return p;
}


codeCache中分配内存,CodeCache使用的是本地内存,有自己的内存管理办法,在后面将会详细介绍。

StubQueue的布局结构如下图所示。

队列中的InterpreterCodelet表示一个小例程,比如iconst_1对应的机器码,invokedynamic对应的机器码,异常处理对应的代码,方法入口点对应的代码,这些代码都是一个个InterpreterCodelet。整个解释器都是由这些小块代码例程组成的,每个小块例程完成解释器的部分功能,以此实现整个解释器。

到此这篇关于认识Java中的Stub与StubQueue的文章就介绍到这了,更多相关Stub与StubQueue内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Springboot中的异步、定时、邮件任务

    详解Springboot中的异步、定时、邮件任务

    这篇文章主要介绍了Springboot中的异步、定时、邮件任务,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-11-11
  • Java实现Kafka生产者消费者代码实例

    Java实现Kafka生产者消费者代码实例

    这篇文章主要介绍了Java实现Kafka生产者消费者代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • mybatis中mapper.xml文件的常用属性及标签讲解

    mybatis中mapper.xml文件的常用属性及标签讲解

    这篇文章主要介绍了mybatis中mapper.xml文件的常用属性及标签讲解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • SpringBoot ApplicationListener事件监听接口使用问题探究

    SpringBoot ApplicationListener事件监听接口使用问题探究

    这篇文章主要介绍了SpringBoot ApplicationListener事件监听接口使用问题,自定义监听器需要实现ApplicationListener接口,实现对应的方法来完成自己的业务逻辑。SpringBoot Application共支持6种事件监听
    2023-04-04
  • Java中对象数组的使用方法详解

    Java中对象数组的使用方法详解

    这篇文章主要介绍了Java中对象数组的使用方法,结合实例形式分析了java对象数组的功能、定义、初始化与相关使用技巧,需要的朋友可以参考下
    2019-08-08
  • Java中使用辗转相除法求最大公约数

    Java中使用辗转相除法求最大公约数

    这篇文章主要介绍了Java中使用辗转相除法求最大公约数,本文直接给出代码实例,需要的朋友可以参考下
    2015-05-05
  • 详解Java中Hibernate的基本原理

    详解Java中Hibernate的基本原理

    持久化是将程序数据在持久状态和瞬时状态间转换的机制。JDBC就是一种持久化机制。文件IO也是一种持久化机制。下面通过本文给大家介绍Java中Hibernate的基本原理,需要的朋友参考下吧
    2017-09-09
  • Java表单重复提交的避免方法

    Java表单重复提交的避免方法

    如何避免表单重复提交,这篇文章就为大家详细介绍了Java表单重复提交的避免方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • window 下 win10 jdk8安装与环境变量的配置过程

    window 下 win10 jdk8安装与环境变量的配置过程

    这篇文章主要介绍了window 下 win10 jdk8安装与环境变量的配置,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • Java的分支结构与循环你知道多少

    Java的分支结构与循环你知道多少

    这篇文章主要为大家详细介绍了Java的分支结构与循环,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02

最新评论