|
@@ -2319,6 +2319,11 @@ public:
|
|
|
// the C++ thread and the java threading library, ensuring that we register/unregister as needed,
|
|
|
// and that any thread_local function contexts are destroyed before we detach from the java thread
|
|
|
|
|
|
+interface IJavaEmbedFunctionContext : public IEmbedFunctionContext
|
|
|
+{
|
|
|
+ virtual void endThread() = 0;
|
|
|
+};
|
|
|
+
|
|
|
class JavaThreadContext
|
|
|
{
|
|
|
public:
|
|
@@ -2342,7 +2347,15 @@ public:
|
|
|
// exiting."
|
|
|
globalState->javaVM->DetachCurrentThread();
|
|
|
}
|
|
|
-
|
|
|
+ void endThread()
|
|
|
+ {
|
|
|
+ persistedObjects.kill();
|
|
|
+ ForEachItemIn(idx, contexts)
|
|
|
+ {
|
|
|
+ auto &context = contexts.item(idx);
|
|
|
+ context.endThread();
|
|
|
+ }
|
|
|
+ }
|
|
|
jobject getSystemClassLoader()
|
|
|
{
|
|
|
jobject systemClassLoaderObj = JNIenv->CallStaticObjectMethod(javaLangClassLoaderClass, cl_getSystemClassLoader);
|
|
@@ -2370,7 +2383,7 @@ public:
|
|
|
JavaObjectXmlWriter x(JNIenv, result, name, *esdl, esdlservice, *writer);
|
|
|
x.write();
|
|
|
}
|
|
|
- void registerContext(IEmbedFunctionContext *ctx)
|
|
|
+ void registerContext(IJavaEmbedFunctionContext *ctx)
|
|
|
{
|
|
|
// Note - this object is thread-local so no need for a critsec
|
|
|
contexts.append(*ctx);
|
|
@@ -2421,7 +2434,7 @@ public:
|
|
|
return p->instance;
|
|
|
}
|
|
|
private:
|
|
|
- IArrayOf<IEmbedFunctionContext> contexts;
|
|
|
+ IArrayOf<IJavaEmbedFunctionContext> contexts;
|
|
|
StringMapOf<PersistedObject> persistedObjects = { false };
|
|
|
StringMapOf<PersistedObject> loaders = { false };
|
|
|
};
|
|
@@ -3196,11 +3209,11 @@ private:
|
|
|
// Objects of class JavaEmbedImportContext are created locally for each call of a function, or thread-local to persist from one call to the next.
|
|
|
// Methods in here do not need to be thread-safe
|
|
|
|
|
|
-class JavaEmbedImportContext : public CInterfaceOf<IEmbedFunctionContext>
|
|
|
+class JavaEmbedImportContext : public CInterfaceOf<IJavaEmbedFunctionContext>
|
|
|
{
|
|
|
public:
|
|
|
- JavaEmbedImportContext(ICodeContext *codeCtx, JavaThreadContext *_sharedCtx, jobject _instance, unsigned flags, const char *options, const IThorActivityContext *_activityContext)
|
|
|
- : sharedCtx(_sharedCtx), JNIenv(sharedCtx->JNIenv), instance(_instance), activityContext(_activityContext)
|
|
|
+ JavaEmbedImportContext(ICodeContext *codeCtx, JavaThreadContext *_sharedCtx, jobject _instance, unsigned _flags, const char *options, const IThorActivityContext *_activityContext)
|
|
|
+ : sharedCtx(_sharedCtx), JNIenv(sharedCtx->JNIenv), instance(_instance), flags(_flags), activityContext(_activityContext)
|
|
|
{
|
|
|
argcount = 0;
|
|
|
argsig = NULL;
|
|
@@ -3271,6 +3284,21 @@ public:
|
|
|
if (classLoader)
|
|
|
JNIenv->DeleteGlobalRef(classLoader);
|
|
|
}
|
|
|
+ virtual void endThread() override
|
|
|
+ {
|
|
|
+ instance = nullptr;
|
|
|
+ if (javaClass)
|
|
|
+ {
|
|
|
+ JNIenv->DeleteGlobalRef(javaClass);
|
|
|
+ javaClass = nullptr;
|
|
|
+ }
|
|
|
+ if (classLoader)
|
|
|
+ {
|
|
|
+ JNIenv->DeleteGlobalRef(classLoader);
|
|
|
+ classLoader = nullptr;
|
|
|
+ }
|
|
|
+ javaMethodID = nullptr;
|
|
|
+ }
|
|
|
|
|
|
virtual bool getBooleanResult()
|
|
|
{
|
|
@@ -4249,22 +4277,35 @@ public:
|
|
|
}
|
|
|
virtual void enter() override
|
|
|
{
|
|
|
+ reenter(nullptr);
|
|
|
+ }
|
|
|
+ virtual void reenter(ICodeContext *codeCtx) override
|
|
|
+ {
|
|
|
// If we rejig codegen to only call loadCompiledScript etc at construction time, then this will need to do the reinit()
|
|
|
// until we do, it's too early
|
|
|
|
|
|
+ if (codeCtx)
|
|
|
+ engine = codeCtx->queryEngineContext();
|
|
|
+ else if (flags & EFthreadlocal && persistMode > persistThread)
|
|
|
+ {
|
|
|
+ StringBuffer s;
|
|
|
+ throw MakeStringException(0, "javaembed: In method %s: Workunit must be recompiled to support this persist mode", getReportName(s).str());
|
|
|
+ }
|
|
|
+
|
|
|
// Create a new frame for local references and increase the capacity
|
|
|
// of those references to 64 (default is 16)
|
|
|
+
|
|
|
JNIenv->PushLocalFrame(64);
|
|
|
}
|
|
|
virtual void exit() override
|
|
|
{
|
|
|
if (persistMode==persistNone)
|
|
|
instance = 0; // otherwise we leave it for next call as it saves a lot of time looking it up
|
|
|
- JNIenv->PopLocalFrame(nullptr);
|
|
|
iterators.kill();
|
|
|
#ifdef FORCE_GC
|
|
|
forceGC(JNIenv);
|
|
|
#endif
|
|
|
+ JNIenv->PopLocalFrame(nullptr);
|
|
|
}
|
|
|
|
|
|
protected:
|
|
@@ -4565,6 +4606,7 @@ protected:
|
|
|
jobject instance = nullptr; // class instance of object to call methods on
|
|
|
const IThorActivityContext *activityContext = nullptr;
|
|
|
|
|
|
+ unsigned flags = 0;
|
|
|
unsigned nodeNum = 0;
|
|
|
StringAttr globalScopeKey;
|
|
|
PersistMode persistMode = persistNone; // Defines the lifetime of the java object for which this is called.
|
|
@@ -4598,17 +4640,20 @@ protected:
|
|
|
static __thread JavaThreadContext* threadContext; // We reuse per thread, for speed
|
|
|
static __thread ThreadTermFunc threadHookChain;
|
|
|
|
|
|
-static void releaseContext()
|
|
|
+static void releaseContext(bool isPooled)
|
|
|
{
|
|
|
if (threadContext)
|
|
|
{
|
|
|
- delete threadContext;
|
|
|
- threadContext = NULL;
|
|
|
+ threadContext->endThread();
|
|
|
+ if (!isPooled)
|
|
|
+ {
|
|
|
+ delete threadContext;
|
|
|
+ threadContext = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
if (threadHookChain)
|
|
|
{
|
|
|
- (*threadHookChain)();
|
|
|
- threadHookChain = NULL;
|
|
|
+ (*threadHookChain)(isPooled);
|
|
|
}
|
|
|
}
|
|
|
|