目录
2、allocate_block和release_block
3、allocate_handle和rebuild_free_list
在Hotspot JNIEnv API详解(一)中我们讲到了JNI中有四种引用类型,JNIInvalidRefType无效引用,JNILocalRefType本地引用,JNIGlobalRefType全局引用,JNIWeakGlobalRefType全局弱引用,本地引用类似于方法调用中局部变量对应的对象引用,全局引用类似于类静态变量对应的对象引用,全局弱引用对应Java中的PhantomReferences虚引用。Java代码的解释执行过程中并没有所谓的引用类型,为啥本地代码需要引入引用类型了?Java代码中引用或本地代码中的引用究竟有啥区别?本地引用在本地方法结束后自动销毁,全局引用必须手动调用DeleteGlobalRef方法才能释放对象引用,这是怎么实现的?
一、JNI引用操作API
JNI引用操作的API的用法和示例在Hotspot JNIEnv API详解(一)都有说明,这里重点关注其源码实现,具体实现在hotspot/src/share/vm/prims/jni.cpp中,核心代码说明如下:
JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref))
//resolve方法是从ref解析出oop
Handle ref_handle(thread, JNIHandles::resolve(ref));
//创建全局引用
jobject ret = JNIHandles::make_global(ref_handle);
return ret;
JNI_END
JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref))
//删除全局引用
JNIHandles::destroy_global(ref);
JNI_END
JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref))
//创建本地引用,resolve方法同上
jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref));
return ret;
JNI_END
JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj))
//删除本地引用
JNIHandles::destroy_local(obj);
JNI_END
JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
//同上,创建全局弱引用
Handle ref_handle(thread, JNIHandles::resolve(ref));
jweak ret = JNIHandles::make_weak_global(ref_handle);
return ret;
JNI_END
JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
//删除全局弱引用
JNIHandles::destroy_weak_global(ref);
JNI_END
JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj))
//条件判断不同的引用类型
jobjectRefType ret;
if (JNIHandles::is_local_handle(thread, obj) ||
JNIHandles::is_frame_handle(thread, obj))
ret = JNILocalRefType;
else if (JNIHandles::is_global_handle(obj))
ret = JNIGlobalRefType;
else if (JNIHandles::is_weak_global_handle(obj))
ret = JNIWeakGlobalRefType;
else
ret = JNIInvalidRefType;
return ret;
JNI_END
JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity))
//只是校验下参数是否合法
if (capacity < 0 ||
((MaxJNILocalCapacity > 0) && (capacity > MaxJNILocalCapacity))) {
return JNI_ERR;
}
//原来的active_handles
JNIHandleBlock* old_handles = thread->active_handles();
//创建新的JNIHandleBlock
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
assert(new_handles != NULL, "should not be NULL");
//将原来的active_handles设置为的新的JNIHandleBlock的pop_frame_link,即通过pop_frame_link可以不断往上
//追溯至最开始的active_handles
new_handles->set_pop_frame_link(old_handles);
//将新创建的JNIHandleBlock设置为active_handles
thread->set_active_handles(new_handles);
jint ret = JNI_OK;
return ret;
JNI_END
JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result))
Handle result_handle(thread, JNIHandles::resolve(result));
JNIHandleBlock* old_handles = thread->active_handles();
//当前JNIHandleBlock上一个的JNIHandleBlock
JNIHandleBlock* new_handles = old_handles->pop_frame_link();
if (new_handles != NULL) {
//active_handles恢复至原来的JNIHandleBlock
thread->set_active_handles(new_handles);
//old_handles释放
old_handles->set_pop_frame_link(NULL); // clear link we won't release new_handles below
JNIHandleBlock::release_block(old_handles, thread); // may block
result = JNIHandles::make_local(thread, result_handle());
}
return result;
JNI_END
从上述源码可知,JNI引用操作实际使用JNIHandles实现的。
二、Handle
Handle相当于一个值对象(ValueObj,即目标值的一个包装类),本身可以作为参数或者返回值,通过操作符重载可以像直接使用值使用Handle。该对象主要是在垃圾回收期间保护用来保护oop,即通过Handle实现垃圾回收期间对象复制导致oop发生改变但oop使用方无感知,因此JVM要求oop无论是作为参数还是返回值必须使用Handle来传递。其定义在hotspot/src/share/vm/runtime/handles.hpp中,实现在同目录下的handles.cpp中,具体定义如下:
class Handle VALUE_OBJ_CLASS_SPEC {
private:
//目标值,注意oop本身实际是oopDesc*的别名,即此处是oopDesc实例的指针的指针
oop* _handle;
protected:
//这两个方法都是返回oop,non_null_obj做了非空校验
oop obj() const { return _handle == NULL ? (oop)NULL : *_handle; }
oop non_null_obj() const { assert(_handle != NULL, "resolving NULL handle"); return *_handle; }
public:
//构建空对象
Handle() { _handle = NULL; }
//底层实现会获取当前线程
Handle(oop obj);
//底层实现会校验thread是否是当前线程
Handle(Thread* thread, oop obj);
//操作符重载
oop operator () () const { return obj(); }
oop operator -> () const { return non_null_obj(); }
bool operator == (oop o) const { return obj() == o; }
bool operator == (const Handle& h) const { return obj() == h.obj(); }
//非空
bool is_null() const { return _handle == NULL; }
bool not_null() const { return _handle != NULL; }
// Debugging
void print() { obj()->print(); }
//_handle不用从当前线程分配内存,直接赋值成目标值,这个方法很少使用
//dummy是无效参数,避免同Handle(oop obj)混淆
Handle(oop *handle, bool dummy) { _handle = handle; }
//直接访问_handle,因为C是值复制,所以这种方式无法保证原来的值是有效的,使用不安全
oop* raw_value() { return _handle; }
//获取原始的oop
static oop raw_resolve(oop *handle) { return handle == NULL ? (oop)NULL : *handle; }
};
不同oop对应的Handle不同,Handle是所有类型的Handle的父类,其他子类都是通过宏定义实现的,如下图:
即Handle的子类包括instanceHandle,arrayHandle,objArrayHandle,typeArrayHandle,子类的构造方法跟Handle一致,只是加了一步oop类型校验。
Handle的实现在hotspot/src/share/vm/runtime/handles.inline.hpp中,相关源码说明如下:
inline Handle::Handle(oop obj) {
if (obj == NULL) {
_handle = NULL;
} else {
//handle_area()方法返回当前线程的_handle_area属性,该属性是HandleArea实例指针
//然后通过HandleArea