Skip to content

Commit

Permalink
Unregister all jni binding when terminating gdkotlin.
Browse files Browse the repository at this point in the history
  • Loading branch information
CedNaru committed Apr 27, 2024
1 parent a0dd415 commit 6797d61
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 69 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/gd_kotlin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ bool GDKotlin::load_bootstrap() {
bool GDKotlin::initialize_core_library() {
jni::Env env {jni::Jvm::current_env()};

if (!JvmManager::initialize_jni_classes(env, bootstrap_class_loader)) { return false; }
if (!JvmManager::initialize_jvm_wrappers(env, bootstrap_class_loader)) { return false; }

if (user_configuration.max_string_size != -1) {
LongStringQueue::get_instance().set_string_max_size(env, user_configuration.max_string_size);
Expand Down Expand Up @@ -307,7 +307,7 @@ void GDKotlin::finalize_core_library() const {
LOG_VERBOSE("JVM GC thread was closed");
MemoryManager::get_instance().clean_up(env);
}
JvmManager::destroy_jni_classes();
JvmManager::finalize_jvm_wrappers(env, bootstrap_class_loader);
}

void GDKotlin::unload_boostrap() {
Expand Down
5 changes: 5 additions & 0 deletions src/jni/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ namespace jni {
env.check_exceptions();
}

void JClass::unregister_natives(Env& env) {
env.env->UnregisterNatives((jclass) obj);
env.check_exceptions();
}

MethodId JClass::get_constructor_method_id(Env& env, const char* signature) {
return get_method_id(env, "<init>", signature);
}
Expand Down
2 changes: 2 additions & 0 deletions src/jni/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ namespace jni {

void register_natives(Env& env, Vector<JNativeMethod> methods);

void unregister_natives(Env& env);

JObject call_static_object_method(Env& env, MethodId method, jvalue* args = {});

JObject get_static_object_field(Env& env, FieldId field);
Expand Down
29 changes: 25 additions & 4 deletions src/jvm_wrapper/jvm_instance_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ public:
clazz.delete_local_ref(p_env); \
} \
\
static void finalize_jni_binding(jni::Env& p_env, ClassLoader* class_loader) { \
jni::JClass clazz; \
if (class_loader) { \
clazz = class_loader->load_class(p_env, get_fully_qualified_name()); \
} else { \
clazz = p_env.find_class(get_fully_qualified_name()); \
} \
\
clazz.unregister_natives(p_env); \
clazz.delete_local_ref(p_env); \
} \
\
private:

/**
Expand All @@ -53,16 +65,14 @@ class JvmInstanceWrapper {

public:
bool is_ref_weak() const;

const jni::JObject& get_wrapped() const;

void swap_to_strong_unsafe(jni::Env& p_env);

void swap_to_weak_unsafe(jni::Env& p_env);

static const char* get_fully_qualified_name();

static bool initialize(jni::Env& p_env, ClassLoader* class_loader);
static Derived* create_instance(jni::Env& p_env, ClassLoader* class_loader);
static void finalize(jni::Env& p_env, ClassLoader* class_loader);
};

template<class Derived, const char* FqName>
Expand All @@ -72,6 +82,12 @@ JvmInstanceWrapper<Derived, FqName>::JvmInstanceWrapper(jni::Env& p_env, jni::JO
p_wrapped.delete_local_ref(p_env);
}

template<class Derived, const char* FqName>
bool JvmInstanceWrapper<Derived, FqName>::initialize(jni::Env& p_env, ClassLoader* class_loader) {
Derived::initialize_jni_binding(p_env, class_loader);
return true;
}

template<class Derived, const char* FqName>
Derived* JvmInstanceWrapper<Derived, FqName>::create_instance(jni::Env& p_env, ClassLoader* class_loader) {
jni::JClass cls;
Expand All @@ -85,6 +101,11 @@ Derived* JvmInstanceWrapper<Derived, FqName>::create_instance(jni::Env& p_env, C
return new Derived(p_env, instance);
}

template<class Derived, const char* FqName>
void JvmInstanceWrapper<Derived, FqName>::finalize(jni::Env& p_env, ClassLoader* class_loader) {
Derived::finalize_jni_binding(p_env, class_loader);
}

template<class Derived, const char* FqName>
JvmInstanceWrapper<Derived, FqName>::~JvmInstanceWrapper() {
jni::Env env {jni::Jvm::current_env()};
Expand Down
44 changes: 22 additions & 22 deletions src/jvm_wrapper/jvm_singleton_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,8 @@ protected: \
*/
template<class Derived, const char* FqName>
class JvmSingletonWrapper : public JvmInstanceWrapper<Derived, FqName> {
friend class JvmManager;

static Derived* _instance;

static bool initialize(jni::Env& p_env, ClassLoader* class_loader);
static void destroy();

protected:
JvmSingletonWrapper(jni::Env& p_env, jni::JObject p_wrapped);
~JvmSingletonWrapper() = default;
Expand All @@ -51,24 +46,11 @@ class JvmSingletonWrapper : public JvmInstanceWrapper<Derived, FqName> {
JvmSingletonWrapper<Derived, FqName>& operator=(JvmSingletonWrapper<Derived, FqName>&&) noexcept = delete;
JvmSingletonWrapper(JvmSingletonWrapper<Derived, FqName>&& instance) noexcept = delete;

static Derived* create_instance(jni::Env& p_env);
static bool initialize(jni::Env& p_env, ClassLoader* class_loader);
static Derived* create_instance(jni::Env& p_env, ClassLoader* class_loader);
static void finalize(jni::Env& p_env, ClassLoader* class_loader);
};

template<class Derived, const char* FqName>
Derived* JvmSingletonWrapper<Derived, FqName>::create_instance(jni::Env& p_env) {
LOG_ERROR("Can't create a new instance of a this class. Returning the singleton instead");
return _instance;
}

template<class Derived, const char* FqName>
Derived* JvmSingletonWrapper<Derived, FqName>::_instance {nullptr};

template<class Derived, const char* FqName>
Derived& JvmSingletonWrapper<Derived, FqName>::get_instance() {
JVM_DEV_ASSERT(_instance, String(FqName) + " singleton is not initialized.");
return *_instance;
}

template<class Derived, const char* FqName>
bool JvmSingletonWrapper<Derived, FqName>::initialize(jni::Env& p_env, ClassLoader* class_loader) {
JVM_DEV_ASSERT(!_instance, String(FqName) + " singleton is already initialized.");
Expand All @@ -91,10 +73,28 @@ bool JvmSingletonWrapper<Derived, FqName>::initialize(jni::Env& p_env, ClassLoad
return true;
}


template<class Derived, const char* FqName>
Derived* JvmSingletonWrapper<Derived, FqName>::create_instance(jni::Env& p_env, ClassLoader* class_loader) {
JVM_DEV_ASSERT(true, "Can't create a new instance of a this class. Returning the singleton instead");
return _instance;
}

template<class Derived, const char* FqName>
void JvmSingletonWrapper<Derived, FqName>::destroy() {
void JvmSingletonWrapper<Derived, FqName>::finalize(jni::Env& p_env, ClassLoader* class_loader) {
JVM_DEV_ASSERT(_instance, String(FqName) + " singleton is not initialized.");
delete _instance;
_instance = nullptr;
Derived::finalize_jni_binding(p_env, class_loader);
}

template<class Derived, const char* FqName>
Derived* JvmSingletonWrapper<Derived, FqName>::_instance {nullptr};

template<class Derived, const char* FqName>
Derived& JvmSingletonWrapper<Derived, FqName>::get_instance() {
JVM_DEV_ASSERT(_instance, String(FqName) + " singleton is not initialized.");
return *_instance;
}

template<class Derived, const char* FqName>
Expand Down
81 changes: 43 additions & 38 deletions src/lifecycle/jvm_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,7 @@ bool JvmManager::initialize_or_get_jvm(void* lib_handle, JvmUserConfiguration& u
return true;
}

bool JvmManager::initialize_jni_classes(jni::Env& p_env, ClassLoader* class_loader) {
Bootstrap::initialize_jni_binding(p_env, class_loader);
KtObject::initialize_jni_binding(p_env, class_loader);
KtPropertyInfo::initialize_jni_binding(p_env, class_loader);
KtProperty::initialize_jni_binding(p_env, class_loader);
KtConstructor::initialize_jni_binding(p_env, class_loader);
KtSignalInfo::initialize_jni_binding(p_env, class_loader);
KtRpcConfig::initialize_jni_binding(p_env, class_loader);
KtFunctionInfo::initialize_jni_binding(p_env, class_loader);
KtFunction::initialize_jni_binding(p_env, class_loader);
KtClass::initialize_jni_binding(p_env, class_loader);

bool JvmManager::initialize_jvm_wrappers(jni::Env& p_env, ClassLoader* class_loader) {
return TransferContext::initialize(p_env, class_loader)
&& TypeManager::initialize(p_env, class_loader)
&& LongStringQueue::initialize(p_env, class_loader)
Expand All @@ -123,34 +112,50 @@ bool JvmManager::initialize_jni_classes(jni::Env& p_env, ClassLoader* class_load
&& bridges::PackedInt64IntArrayBridge::initialize(p_env, class_loader)
&& bridges::PackedStringArrayBridge::initialize(p_env, class_loader)
&& bridges::PackedVector2ArrayBridge::initialize(p_env, class_loader)
&& bridges::PackedVector3ArrayBridge::initialize(p_env, class_loader);
&& bridges::PackedVector3ArrayBridge::initialize(p_env, class_loader)
&& Bootstrap::initialize(p_env, class_loader)
&& KtObject::initialize(p_env, class_loader)
&& KtPropertyInfo::initialize(p_env, class_loader)
&& KtProperty::initialize(p_env, class_loader)
&& KtConstructor::initialize(p_env, class_loader)
&& KtSignalInfo::initialize(p_env, class_loader)
&& KtRpcConfig::initialize(p_env, class_loader)
&& KtFunctionInfo::initialize(p_env, class_loader)
&& KtFunction::initialize(p_env, class_loader)
&& KtClass::initialize(p_env, class_loader);
}

void JvmManager::destroy_jni_classes() {
// Singleton
TransferContext::destroy();
TypeManager::destroy();
LongStringQueue::destroy();
MemoryManager::destroy();

bridges::GDPrintBridge::destroy();

bridges::CallableBridge::destroy();
bridges::DictionaryBridge::destroy();
bridges::RidBridge::destroy();
bridges::StringNameBridge::destroy();
bridges::NodePathBridge::destroy();
bridges::VariantArrayBridge::destroy();

bridges::PackedByteArrayBridge::destroy();
bridges::PackedColorArrayBridge::destroy();
bridges::PackedFloat32ArrayBridge::destroy();
bridges::PackedFloat64ArrayBridge::destroy();
bridges::PackedInt32IntArrayBridge::destroy();
bridges::PackedInt64IntArrayBridge::destroy();
bridges::PackedStringArrayBridge::destroy();
bridges::PackedVector2ArrayBridge::destroy();
bridges::PackedVector3ArrayBridge::destroy();
void JvmManager::finalize_jvm_wrappers(jni::Env& p_env, ClassLoader* class_loader) {
TransferContext::finalize(p_env, class_loader);
TypeManager::finalize(p_env, class_loader);
LongStringQueue::finalize(p_env, class_loader);
MemoryManager::finalize(p_env, class_loader);
bridges::GDPrintBridge::finalize(p_env, class_loader);
bridges::CallableBridge::finalize(p_env, class_loader);
bridges::DictionaryBridge::finalize(p_env, class_loader);
bridges::RidBridge::finalize(p_env, class_loader);
bridges::StringNameBridge::finalize(p_env, class_loader);
bridges::NodePathBridge::finalize(p_env, class_loader);
bridges::VariantArrayBridge::finalize(p_env, class_loader);
bridges::PackedByteArrayBridge::finalize(p_env, class_loader);
bridges::PackedColorArrayBridge::finalize(p_env, class_loader);
bridges::PackedFloat32ArrayBridge::finalize(p_env, class_loader);
bridges::PackedFloat64ArrayBridge::finalize(p_env, class_loader);
bridges::PackedInt32IntArrayBridge::finalize(p_env, class_loader);
bridges::PackedInt64IntArrayBridge::finalize(p_env, class_loader);
bridges::PackedStringArrayBridge::finalize(p_env, class_loader);
bridges::PackedVector2ArrayBridge::finalize(p_env, class_loader);
bridges::PackedVector3ArrayBridge::finalize(p_env, class_loader);
Bootstrap::finalize(p_env, class_loader);
KtObject::finalize(p_env, class_loader);
KtPropertyInfo::finalize(p_env, class_loader);
KtProperty::finalize(p_env, class_loader);
KtConstructor::finalize(p_env, class_loader);
KtSignalInfo::finalize(p_env, class_loader);
KtRpcConfig::finalize(p_env, class_loader);
KtFunctionInfo::finalize(p_env, class_loader);
KtFunction::finalize(p_env, class_loader);
KtClass::finalize(p_env, class_loader);
}

void JvmManager::close_jvm() {
Expand Down
4 changes: 2 additions & 2 deletions src/lifecycle/jvm_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
class JvmManager {
public:
static bool initialize_or_get_jvm(void* lib_handle, JvmUserConfiguration& user_configuration, JvmOptions& jvm_options);
static bool initialize_jni_classes(jni::Env& p_env, ClassLoader* class_loader);
static void destroy_jni_classes();
static bool initialize_jvm_wrappers(jni::Env& p_env, ClassLoader* class_loader);
static void finalize_jvm_wrappers(jni::Env& p_env, ClassLoader* class_loader);
static void close_jvm();
};

Expand Down

0 comments on commit 6797d61

Please sign in to comment.