From: Marcus Comstedt Date: Sun, 1 Nov 2015 22:29:32 +0000 (+0100) Subject: Java: Fix leaking global refs X-Git-Tag: libsigrok-0.4.0~128 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=e13648d0416aa0cb3c81f234389c92a30d46d527;p=libsigrok.git Java: Fix leaking global refs This fixes issue #690. --- diff --git a/bindings/java/org/sigrok/core/classes/classes.i b/bindings/java/org/sigrok/core/classes/classes.i index 681515c4..dda333df 100644 --- a/bindings/java/org/sigrok/core/classes/classes.i +++ b/bindings/java/org/sigrok/core/classes/classes.i @@ -271,6 +271,40 @@ namespace { } } +/* "Smartpointer" for Java references. */ + +%inline { +namespace { + class GlobalRefBase + { + protected: + GlobalRefBase (JavaVM *jvm, jobject ref); + GlobalRefBase (const GlobalRefBase &ref) = delete; + ~GlobalRefBase (); + JavaVM *jvm; + jobject jref; + }; + GlobalRefBase::GlobalRefBase (JavaVM *jvm, jobject ref) : jvm(jvm), jref(0) { + ScopedEnv env(jvm); + if (env && ref) + jref = env->NewGlobalRef(ref); + } + GlobalRefBase::~GlobalRefBase () { + ScopedEnv env(jvm); + if(env && jref) + env->DeleteGlobalRef(jref); + } + template + class GlobalRef : private GlobalRefBase + { + public: + GlobalRef (JavaVM *jvm, Jtype ref) : GlobalRefBase(jvm, ref) {} + GlobalRef (const GlobalRef &ref) : GlobalRefBase(ref.jvm, ref.jref) {} + operator Jtype () const { return static_cast(jref); } + }; +} +} + /* Support Java log callbacks. */ %typemap(javaimports) sigrok::Context @@ -294,10 +328,9 @@ typedef jobject jlogcallback; jclass obj_class = env->GetObjectClass(obj); jmethodID method = env->GetMethodID(obj_class, "run", "(Lorg/sigrok/core/classes/LogLevel;Ljava/lang/String;)V"); - jclass LogLevel = (jclass) env->NewGlobalRef( - env->FindClass("org/sigrok/core/classes/LogLevel")); + GlobalRef LogLevel(jvm, env->FindClass("org/sigrok/core/classes/LogLevel")); jmethodID LogLevel_init = env->GetMethodID(LogLevel, "", "(JZ)V"); - jobject obj_ref = env->NewGlobalRef(obj); + GlobalRef obj_ref(jvm, obj); $self->set_log_callback([=] ( const sigrok::LogLevel *loglevel, @@ -341,13 +374,11 @@ typedef jobject jdatafeedcallback; jclass obj_class = env->GetObjectClass(obj); jmethodID method = env->GetMethodID(obj_class, "run", "(Lorg/sigrok/core/classes/Device;Lorg/sigrok/core/classes/Packet;)V"); - jclass Device = (jclass) env->NewGlobalRef( - env->FindClass("org/sigrok/core/classes/Device")); + GlobalRef Device(jvm, env->FindClass("org/sigrok/core/classes/Device")); jmethodID Device_init = env->GetMethodID(Device, "", "(JZ)V"); - jclass Packet = (jclass) env->NewGlobalRef( - env->FindClass("org/sigrok/core/classes/Packet")); + GlobalRef Packet(jvm, env->FindClass("org/sigrok/core/classes/Packet")); jmethodID Packet_init = env->GetMethodID(Packet, "", "(JZ)V"); - jobject obj_ref = env->NewGlobalRef(obj); + GlobalRef obj_ref(jvm, obj); $self->add_datafeed_callback([=] ( std::shared_ptr device,