diff --git a/.gitignore b/.gitignore index 1e0b2068..073b99f4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ node-java.cbp *.iml *.kdev4 */.kdev_include_paths +.DS_Store diff --git a/docker/Dockerfile b/docker/Dockerfile index 5b587e68..2cff6665 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -5,17 +5,17 @@ RUN apt-get install -y curl wget tar git python build-essential # Java RUN \ - wget https://javadl.oracle.com/webapps/download/GetFile/1.8.0_261-b12/a4634525489241b9a9e1aa73d9e118e6/linux-i586/jdk-8u261-linux-x64.tar.gz -O /opt/jdk-8u261-linux-x64.tar.gz \ - && tar -xzf /opt/jdk-8u261-linux-x64.tar.gz -C /opt \ - && rm /opt/jdk-8u261-linux-x64.tar.gz \ - && ln -s /opt/jdk1.8.0_261 /opt/jdk + wget --continue --no-check-certificate -O /opt/jdk-8u191-linux-x64.tar.gz --header "Cookie: oraclelicense=a" http://download.oracle.com/otn-pub/java/jdk/8u191-b12/2787e4a523244c269598db4e85c51e0c/jdk-8u191-linux-x64.tar.gz \ + && tar -xzf /opt/jdk-8u191-linux-x64.tar.gz -C /opt \ + && rm /opt/jdk-8u191-linux-x64.tar.gz \ + && ln -s /opt/jdk1.8.0_191 /opt/jdk ENV PATH $PATH:/opt/jdk/bin ENV JAVA_HOME /opt/jdk ENV _JAVA_OPTIONS -Djava.net.preferIPv4Stack=true # Node RUN \ - wget -O /opt/node-v11.2.0-linux-x64.tar.gz https://nodejs.org/dist/v11.2.0/node-v11.2.0-linux-x64.tar.gz \ + wget -O /opt/node-v11.2.0-linux-x64.tar.gz http://nodejs.org/dist/latest/node-v11.2.0-linux-x64.tar.gz \ && tar -xzf /opt/node-v11.2.0-linux-x64.tar.gz -C /opt \ && rm /opt/node-v11.2.0-linux-x64.tar.gz \ && ln -s /opt/node-v11.2.0-linux-x64 /opt/node diff --git a/find_java_libdir.sh b/find_java_libdir.sh index 0407c39d..55744c2c 100755 --- a/find_java_libdir.sh +++ b/find_java_libdir.sh @@ -47,7 +47,7 @@ main () { target_arch=`uname -m` if [[ -d ${jre_dir}/${target_arch}/classic ]]; then lib_dir="${jre_dir}"/${target_arch}/classic; else lib_dir="${jre_dir}"/${target_arch}/server; fi elif [[ "${os}" == "mac" ]]; then - lib_dir="${jre_dir}/jli" + if [[ -f ${jre_dir}/jli/libjli.dylib ]]; then lib_dir="${jre_dir}"/jli; else lib_dir="${jre_dir}"; fi else local arch if [[ "${target_arch}" =~ (32|386) ]]; then diff --git a/package-lock.json b/package-lock.json index c2cc7695..0b0310b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "java", - "version": "0.12.0", + "version": "0.12.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -581,9 +581,9 @@ } }, "find-java-home": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/find-java-home/-/find-java-home-0.2.0.tgz", - "integrity": "sha512-nq5PFOHxE1VSEbdDVkLoA2bAcRnG4ETqJO8ipFq3glIWA52hdWCXYX3emuUyMAQfaqFU4Ea85gqcgaPmOApEPA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-java-home/-/find-java-home-1.1.0.tgz", + "integrity": "sha512-bSTCKNZ193UM/+ZZoNDzICAEHcVywovkhsWCkZALjCvRXQ+zXTe/XATrrP4CpxkaP6YFhQJOpyRpH0P2U/woDA==", "requires": { "which": "~1.0.5", "winreg": "~1.2.2" @@ -658,9 +658,9 @@ } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1010,9 +1010,9 @@ } }, "lodash": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", - "integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==" + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.flattendeep": { "version": "4.4.0", @@ -1140,9 +1140,9 @@ "dev": true }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" }, "neo-async": { "version": "2.6.1", diff --git a/package.json b/package.json index 058ff881..8f2e3913 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "async": "2.6.1", "find-java-home": "1.1.0", "glob": "7.1.6", - "lodash": "4.17.15", + "lodash": "4.17.19", "nan": "2.14.1" }, "devDependencies": { diff --git a/src/java.cpp b/src/java.cpp index fb5cfbd5..f71b793a 100644 --- a/src/java.cpp +++ b/src/java.cpp @@ -9,7 +9,6 @@ #include "methodCallBaton.h" #include "node_NodeDynamicProxyClass.h" #include -#include #include #include @@ -23,10 +22,6 @@ threadId v8ThreadId; -std::queue queue_dynamicProxyJsCallData; -uv_mutex_t uvMutex_dynamicProxyJsCall; -uv_async_t uvAsync_dynamicProxyJsCall; - /*static*/ Nan::Persistent Java::s_ct; /*static*/ std::string Java::s_nativeBindingLocation; @@ -54,34 +49,11 @@ bool v8ThreadIdEquals(threadId a, threadId b) { #endif } -void EIO_CallJs(DynamicProxyJsCallData *callData); - -void uvAsyncCb_dynamicProxyJsCall(uv_async_t *handle) { - DynamicProxyJsCallData *callData; - do { - uv_mutex_lock(&uvMutex_dynamicProxyJsCall); - if(!queue_dynamicProxyJsCallData.empty()) { - callData = queue_dynamicProxyJsCallData.front(); - queue_dynamicProxyJsCallData.pop(); - } else { - callData = NULL; - } - uv_mutex_unlock(&uvMutex_dynamicProxyJsCall); - - if(callData) { - EIO_CallJs(callData); - } - } while(callData); -} - /*static*/ void Java::Init(v8::Local target) { Nan::HandleScope scope; v8ThreadId = my_getThreadId(); - uv_mutex_init(&uvMutex_dynamicProxyJsCall); - uv_async_init(uv_default_loop(), &uvAsync_dynamicProxyJsCall, uvAsyncCb_dynamicProxyJsCall); - v8::Local t = Nan::New(New); s_ct.Reset(t); t->InstanceTemplate()->SetInternalFieldCount(1); @@ -1239,6 +1211,9 @@ NAN_METHOD(Java::instanceOf) { info.GetReturnValue().Set(Nan::New(res)); } +void EIO_CallJs(uv_work_t* req) { +} + template std::string to_string(T value) { std::ostringstream os; @@ -1246,22 +1221,23 @@ std::string to_string(T value) { return os.str(); } -void EIO_CallJs(DynamicProxyJsCallData *callData) { - DynamicProxyData* dynamicProxyData = callData->dynamicProxyData; - - assert(callData->done == 0); - +#if NODE_MINOR_VERSION >= 10 +void EIO_AfterCallJs(uv_work_t* req, int status) { +#else +void EIO_AfterCallJs(uv_work_t* req) { +#endif + DynamicProxyData* dynamicProxyData = static_cast(req->data); if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } - callData->result = NULL; + dynamicProxyData->result = NULL; JNIEnv* env; int ret = dynamicProxyData->java->getJvm()->GetEnv((void**)&env, JNI_BEST_VERSION); if (ret != JNI_OK) { - callData->throwableClass = "java/lang/IllegalStateException"; - callData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string(ret); - callData->done = DYNAMIC_PROXY_JS_ERROR; + dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; + dynamicProxyData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string(ret); + dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } @@ -1275,24 +1251,24 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { jobject javaResult; v8::Local dynamicProxyDataFunctions = Nan::New(dynamicProxyData->functions); - v8::Local fnObj = dynamicProxyDataFunctions->Get(Nan::GetCurrentContext(), Nan::New(callData->methodName.c_str()).ToLocalChecked()).ToLocalChecked(); + v8::Local fnObj = dynamicProxyDataFunctions->Get(Nan::GetCurrentContext(), Nan::New(dynamicProxyData->methodName.c_str()).ToLocalChecked()).ToLocalChecked(); if(fnObj->IsUndefined() || fnObj->IsNull()) { - callData->throwableClass = "java/lang/NoSuchMethodError"; - callData->throwableMessage = "Could not find js function " + callData->methodName; - callData->done = DYNAMIC_PROXY_JS_ERROR; + dynamicProxyData->throwableClass = "java/lang/NoSuchMethodError"; + dynamicProxyData->throwableMessage = "Could not find js function " + dynamicProxyData->methodName; + dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } if(!fnObj->IsFunction()) { - callData->throwableClass = "java/lang/IllegalStateException"; - callData->throwableMessage = callData->methodName + " is not a function"; - callData->done = DYNAMIC_PROXY_JS_ERROR; + dynamicProxyData->throwableClass = "java/lang/IllegalStateException"; + dynamicProxyData->throwableMessage = dynamicProxyData->methodName + " is not a function"; + dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } fn = fnObj.As(); - if(callData->args) { - v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, callData->args)); + if(dynamicProxyData->args) { + v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, dynamicProxyData->args)); argc = v8Args->Length(); } else { argc = 0; @@ -1307,11 +1283,11 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { v8Result = Nan::Call(fn, dynamicProxyDataFunctions, argc, argv).FromMaybe(v8::Local()); delete[] argv; if (tryCatch.HasCaught()) { - callData->throwableClass = "node/NodeJsException"; + dynamicProxyData->throwableClass = "node/NodeJsException"; Nan::Utf8String message(tryCatch.Message()->Get()); - callData->throwableMessage = std::string(*message); + dynamicProxyData->throwableMessage = std::string(*message); tryCatch.Reset(); - callData->done = DYNAMIC_PROXY_JS_ERROR; + dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR; return; } @@ -1321,12 +1297,12 @@ void EIO_CallJs(DynamicProxyJsCallData *callData) { javaResult = v8ToJava(env, v8Result); if(javaResult == NULL) { - callData->result = NULL; + dynamicProxyData->result = NULL; } else { - callData->result = env->NewGlobalRef(javaResult); + dynamicProxyData->result = env->NewGlobalRef(javaResult); } - callData->done = true; + dynamicProxyData->done = true; } void throwNewThrowable(JNIEnv* env, const char * excClassName, std::string msg) { @@ -1343,37 +1319,37 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo bool hasArgsGlobalRef = false; - DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; - // args needs to be global, you can't send env across thread boundaries - DynamicProxyJsCallData callData; - callData.dynamicProxyData = dynamicProxyData; - callData.args = args; - callData.done = false; - callData.result = NULL; - callData.throwableClass = ""; - callData.throwableMessage = ""; + DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; + dynamicProxyData->args = args; + dynamicProxyData->done = false; + dynamicProxyData->result = NULL; + dynamicProxyData->throwableClass = ""; + dynamicProxyData->throwableMessage = ""; jclass methodClazz = env->FindClass("java/lang/reflect/Method"); jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;"); - callData.methodName = javaObjectToString(env, env->CallObjectMethod(method, method_getName)); + dynamicProxyData->methodName = javaObjectToString(env, env->CallObjectMethod(method, method_getName)); assertNoException(env); + uv_work_t* req = new uv_work_t(); + req->data = dynamicProxyData; if(v8ThreadIdEquals(myThreadId, v8ThreadId)) { - EIO_CallJs(&callData); +#if NODE_MINOR_VERSION >= 10 + EIO_AfterCallJs(req, 0); +#else + EIO_AfterCallJs(req); +#endif } else { if (args) { // if args is not null and we have to kick this across the thread boundary, make it a global ref - callData.args = (jobjectArray) env->NewGlobalRef(args); + dynamicProxyData->args = (jobjectArray) env->NewGlobalRef(args); hasArgsGlobalRef = true; } - uv_mutex_lock(&uvMutex_dynamicProxyJsCall); - queue_dynamicProxyJsCallData.push(&callData); // we wait for work to finish, so ok to pass ref to local var - uv_mutex_unlock(&uvMutex_dynamicProxyJsCall); - uv_async_send(&uvAsync_dynamicProxyJsCall); + uv_queue_work(uv_default_loop(), req, EIO_CallJs, (uv_after_work_cb)EIO_AfterCallJs); - while(!callData.done) { + while(!dynamicProxyData->done) { my_sleep(100); } } @@ -1382,18 +1358,18 @@ JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jo throwNewThrowable(env, "java/lang/IllegalStateException", "dynamicProxyData was corrupted"); } if(hasArgsGlobalRef) { - env->DeleteGlobalRef(callData.args); + env->DeleteGlobalRef(dynamicProxyData->args); } - if (callData.done == DYNAMIC_PROXY_JS_ERROR) { - throwNewThrowable(env, callData.throwableClass.c_str(), callData.throwableMessage); + if (dynamicProxyData->done == DYNAMIC_PROXY_JS_ERROR) { + throwNewThrowable(env, dynamicProxyData->throwableClass.c_str(), dynamicProxyData->throwableMessage); } jobject result = NULL; - if(callData.result) { + if(dynamicProxyData->result) { // need to retain a local ref so that we can return it, otherwise the returned object gets corrupted - result = env->NewLocalRef(callData.result); - env->DeleteGlobalRef(callData.result); + result = env->NewLocalRef(dynamicProxyData->result); + env->DeleteGlobalRef(dynamicProxyData->result); } return result; } diff --git a/src/utils.cpp b/src/utils.cpp index a8f84858..6c899555 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -484,11 +484,7 @@ jvalueType javaGetArrayComponentType(JNIEnv *env, jobjectArray array) { #if (NODE_VERSION_AT_LEAST(4, 0, 0)) v8::Local newArrayBuffer(void* elems, size_t length) { v8::Local ab = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), length); - #if (NODE_MAJOR_VERSION >= 8) - memcpy(ab->GetBackingStore()->Data(), elems, length); - #else - memcpy(ab->GetContents().Data(), elems, length); - #endif + memcpy(ab->GetContents().Data(), elems, length); return ab; } #endif diff --git a/src/utils.h b/src/utils.h index 77f4b5b2..9ba87b11 100644 --- a/src/utils.h +++ b/src/utils.h @@ -37,17 +37,13 @@ struct DynamicProxyData { std::string interfaceName; Nan::Persistent functions; Nan::Persistent jsObject; - unsigned int markerEnd; -}; - -struct DynamicProxyJsCallData { - DynamicProxyData *dynamicProxyData; std::string methodName; jobjectArray args; jobject result; std::string throwableClass; std::string throwableMessage; int done; + unsigned int markerEnd; }; #define DYNAMIC_PROXY_DATA_MARKER_START 0x12345678