浏览代码

HPCC-16097 Memory leak when using Java plugin

Java allocations made when calling iterator for dataset results
would not be released util thread terminated.

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 8 年之前
父节点
当前提交
76b910924e
共有 1 个文件被更改,包括 31 次插入6 次删除
  1. 31 6
      plugins/javaembed/javaembed.cpp

+ 31 - 6
plugins/javaembed/javaembed.cpp

@@ -1097,23 +1097,44 @@ protected:
 
 // A Java function that returns a dataset will return a JavaRowStream object that can be
 // interrogated to return each row of the result in turn
-// Note that we can't cache the JNIEnv here - calls may be made on different threads (though not at the same time).
 
 static JNIEnv *queryJNIEnv();
 
+class JavaLocalFrame
+{
+public:
+    JavaLocalFrame(JNIEnv *_JNIenv, unsigned size = 16) : JNIenv(_JNIenv)
+    {
+        JNIenv->PushLocalFrame(size);
+    }
+    ~JavaLocalFrame()
+    {
+        JNIenv->PopLocalFrame(NULL);
+    }
+private:
+    JNIEnv *JNIenv;
+};
+
 class JavaRowStream : public CInterfaceOf<IRowStream>
 {
 public:
     JavaRowStream(jobject _iterator, IEngineRowAllocator *_resultAllocator)
     : resultAllocator(_resultAllocator)
     {
-        iterator = queryJNIEnv()->NewGlobalRef(_iterator);
+        JNIEnv *JNIenv = queryJNIEnv();
+        iterator = JNIenv->NewGlobalRef(_iterator);
+        // Note that we can't cache the JNIEnv, iterClass, or methodIds here - calls may be made on different threads (though not at the same time).
+    }
+    ~JavaRowStream()
+    {
+        stop();
     }
     virtual const void *nextRow()
     {
         if (!iterator)
             return NULL;
         JNIEnv *JNIenv = queryJNIEnv();
+        JavaLocalFrame lf(JNIenv);
         // Java code would be
         // if (!iterator.hasNext)
         // {
@@ -1145,16 +1166,20 @@ public:
     virtual void stop()
     {
         resultAllocator.clear();
-        if (iterator)
+        JNIEnv *JNIenv = queryJNIEnv();
+        if (JNIenv)
         {
-            queryJNIEnv()->DeleteGlobalRef(iterator);
-            iterator = NULL;
+            if (iterator)
+            {
+                JNIenv->DeleteGlobalRef(iterator);
+                iterator = NULL;
+            }
         }
     }
 
 protected:
     Linked<IEngineRowAllocator> resultAllocator;
-    jobject iterator;;
+    jobject iterator;
 };
 
 const char *esdl2JavaSig(IEsdlDefinition &esdl, const char *esdlType)