Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 56 additions & 94 deletions src/jni/CallbackHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ void CallbackHandlers::Init(Isolate *isolate, ObjectManager *objectManager)
RESOLVE_CLASS_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "resolveClass", "(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Class;");
assert(RESOLVE_CLASS_METHOD_ID != nullptr);

CREATE_INSTANCE_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "createInstance", "([Ljava/lang/Object;II)Ljava/lang/Object;");
assert(CREATE_INSTANCE_METHOD_ID != nullptr);
CURRENT_OBJECTID_FIELD_ID = env.GetFieldID(RUNTIME_CLASS, "currentObjectId", "I");
assert(CURRENT_OBJECTID_FIELD_ID != nullptr);

CACHE_CONSTRUCTOR_METHOD_ID = env.GetMethodID(RUNTIME_CLASS, "cacheConstructor", "(Ljava/lang/Class;[Ljava/lang/Object;)I");
assert(CACHE_CONSTRUCTOR_METHOD_ID != nullptr);
MAKE_INSTANCE_STRONG_ID = env.GetMethodID(RUNTIME_CLASS, "makeInstanceStrong", "(Ljava/lang/Object;I)V");
assert(MAKE_INSTANCE_STRONG_ID != nullptr);

GET_TYPE_METADATA = env.GetStaticMethodID(RUNTIME_CLASS, "getTypeMetadata", "(Ljava/lang/String;I)[Ljava/lang/String;");
assert(GET_TYPE_METADATA != nullptr);
Expand Down Expand Up @@ -80,7 +80,31 @@ bool CallbackHandlers::RegisterInstance(Isolate *isolate, const Local<Object>& j
DEBUG_WRITE("RegisterInstance: Linking new instance");
objectManager->Link(jsObject, javaObjectID, nullptr);

jobject instance = CreateJavaInstance(javaObjectID, fullClassName, argWrapper, generatedJavaClass, isInterface);
// resolve constructor
auto mi = MethodCache::ResolveConstructorSignature(argWrapper, fullClassName, generatedJavaClass, isInterface);

jobject instance;

{
JavaObjectIdScope objIdScope(env, CURRENT_OBJECTID_FIELD_ID, runtime->GetJavaRuntime(), javaObjectID);

if(argWrapper.type == ArgType::Interface)
{
instance = env.NewObject(generatedJavaClass, mi.mid);
}
else
{
// resolve arguments before passing them on to the constructor
JsArgConverter argConverter(argWrapper.args, mi.signature, argWrapper.outerThis);
auto ctorArgs = argConverter.ToArgs();

instance = env.NewObjectA(generatedJavaClass, mi.mid, ctorArgs);
}
}

env.CallVoidMethod(runtime->GetJavaRuntime(), MAKE_INSTANCE_STRONG_ID, instance, javaObjectID);

AdjustAmountOfExternalAllocatedMemory(env, isolate);

JniLocalRef localInstance(instance);
success = !localInstance.IsNull();
Expand Down Expand Up @@ -113,14 +137,14 @@ jclass CallbackHandlers::ResolveClass(Isolate *isolate, const string& fullClassn
{
JEnv env;

//get needed arguments in order to load binding
// get needed arguments in order to load binding
JniLocalRef javaFullClassName(env.NewStringUTF(fullClassname.c_str()));

jobjectArray methodOverrides = GetMethodOverrides(env, implementationObject);

auto runtime = Runtime::GetRuntime(isolate);

//create or load generated binding (java class)
// create or load generated binding (java class)
JniLocalRef generatedClass(env.CallObjectMethod(runtime->GetJavaRuntime(), RESOLVE_CLASS_METHOD_ID, (jstring) javaFullClassName, methodOverrides));
globalRefToGeneratedClass = static_cast<jclass>(env.NewGlobalRef(generatedClass));

Expand Down Expand Up @@ -196,8 +220,8 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
}

entry->memberId = isStatic ?
env.GetStaticMethodID(clazz, methodName, entry->sig) :
env.GetMethodID(clazz, methodName, entry->sig);
env.GetStaticMethodID(clazz, methodName, entry->sig) :
env.GetMethodID(clazz, methodName, entry->sig);

if (entry->memberId == nullptr)
{
Expand All @@ -209,8 +233,8 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
else
{
entry->memberId = isStatic ?
env.GetStaticMethodID(clazz, methodName, entry->sig) :
env.GetMethodID(clazz, methodName, entry->sig);
env.GetStaticMethodID(clazz, methodName, entry->sig) :
env.GetMethodID(clazz, methodName, entry->sig);

if (entry->memberId == nullptr)
{
Expand Down Expand Up @@ -302,7 +326,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
switch (retType)
{
case MethodReturnType::Void:
{
{
if (isStatic)
{
env.CallStaticVoidMethodA(clazz, mid, javaArgs);
Expand All @@ -318,7 +342,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Boolean:
{
{
jboolean result;
if (isStatic)
{
Expand All @@ -336,7 +360,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Byte:
{
{
jbyte result;
if (isStatic)
{
Expand All @@ -354,7 +378,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Char:
{
{
jchar result;
if (isStatic)
{
Expand All @@ -377,7 +401,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Short:
{
{
jshort result;
if (isStatic)
{
Expand All @@ -395,7 +419,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Int:
{
{
jint result;
if (isStatic)
{
Expand All @@ -414,7 +438,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&

}
case MethodReturnType::Long:
{
{
jlong result;
if (isStatic)
{
Expand All @@ -433,7 +457,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Float:
{
{
jfloat result;
if (isStatic)
{
Expand All @@ -451,7 +475,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Double:
{
{
jdouble result;
if (isStatic)
{
Expand All @@ -469,7 +493,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::String:
{
{
jobject result = nullptr;
bool exceptionOccurred;

Expand Down Expand Up @@ -500,7 +524,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
case MethodReturnType::Object:
{
{
jobject result = nullptr;
bool exceptionOccurred;

Expand Down Expand Up @@ -548,7 +572,7 @@ void CallbackHandlers::CallJavaMethod(const Local<Object>& caller, const string&
break;
}
default:
{
{
assert(false);
break;
}
Expand All @@ -569,9 +593,9 @@ int64_t CallbackHandlers::AdjustAmountOfExternalAllocatedMemory(JEnv& env, Isola
int64_t changeInBytes = env.CallLongMethod(runtime->GetJavaRuntime(), GET_CHANGE_IN_BYTES_OF_USED_MEMORY_METHOD_ID);

int64_t adjustedValue = (changeInBytes != 0)
? isolate->AdjustAmountOfExternalAllocatedMemory(changeInBytes)
:
0;
? isolate->AdjustAmountOfExternalAllocatedMemory(changeInBytes)
:
0;

return adjustedValue;
}
Expand All @@ -584,68 +608,6 @@ Local<Object> CallbackHandlers::CreateJSWrapper(Isolate *isolate, jint javaObjec
return objectManager->CreateJSWrapper(javaObjectID, typeName);
}

jobject CallbackHandlers::CreateJavaInstance(int objectID, const std::string& fullClassName, const ArgsWrapper& argWrapper, jclass javaClass, bool isInterface)
{
SET_PROFILER_FRAME();

jobject instance = nullptr;
DEBUG_WRITE("CreateJavaInstance: %s", fullClassName.c_str());

JEnv env;
auto& args = argWrapper.args;

JsArgToArrayConverter argConverter(args, isInterface, argWrapper.outerThis);
if (argConverter.IsValid())
{
jobjectArray javaArgs = argConverter.ToJavaArray();

int ctorId = GetCachedConstructorId(env, args, fullClassName, javaArgs, javaClass);

auto runtime = Runtime::GetRuntime(args.GetIsolate());

jobject obj = env.CallObjectMethod(runtime->GetJavaRuntime(),
CREATE_INSTANCE_METHOD_ID,
javaArgs,
(jint) objectID,
ctorId);

instance = obj;
}
else
{
JsArgToArrayConverter::Error err = argConverter.GetError();
throw NativeScriptException(err.msg);
}

return instance;
}

int CallbackHandlers::GetCachedConstructorId(JEnv& env, const FunctionCallbackInfo<Value>& args, const string& fullClassName, jobjectArray javaArgs, jclass javaClass)
{
int ctorId = -1;
string encodedCtorArgs = MethodCache::EncodeSignature(fullClassName, "<init>", args, false);
auto itFound = s_constructorCache.find(encodedCtorArgs);

if (itFound != s_constructorCache.end())
{
ctorId = itFound->second;
}
else
{
auto runtime = Runtime::GetRuntime(args.GetIsolate());
jint id = env.CallIntMethod(runtime->GetJavaRuntime(), CACHE_CONSTRUCTOR_METHOD_ID, javaClass, javaArgs);

if (env.ExceptionCheck() == JNI_FALSE)
{
ctorId = id;
s_constructorCache.insert(make_pair(encodedCtorArgs, ctorId));
}
}

DEBUG_WRITE("GetCachedConstructorId: encodedCtorArgs=%s, ctorId=%d", encodedCtorArgs.c_str(), ctorId);
return ctorId;
}

//delete the returned local reference after use
jobjectArray CallbackHandlers::GetMethodOverrides(JEnv& env, const Local<Object>& implementationObject)
{
Expand Down Expand Up @@ -702,7 +664,7 @@ void CallbackHandlers::LogMethodCallback(const v8::FunctionCallbackInfo<v8::Valu
e.ReThrowToV8();
}
catch (std::exception e) {
stringstream ss;
stringstream ss;
ss << "Error: c++ exception: " << e.what() << endl;
NativeScriptException nsEx(ss.str());
nsEx.ReThrowToV8();
Expand Down Expand Up @@ -738,7 +700,7 @@ void CallbackHandlers::DumpReferenceTablesMethod()
e.ReThrowToV8();
}
catch (std::exception e) {
stringstream ss;
stringstream ss;
ss << "Error: c++ exception: " << e.what() << endl;
NativeScriptException nsEx(ss.str());
nsEx.ReThrowToV8();
Expand All @@ -764,7 +726,7 @@ void CallbackHandlers::EnableVerboseLoggingMethodCallback(const v8::FunctionCall
e.ReThrowToV8();
}
catch (std::exception e) {
stringstream ss;
stringstream ss;
ss << "Error: c++ exception: " << e.what() << endl;
NativeScriptException nsEx(ss.str());
nsEx.ReThrowToV8();
Expand All @@ -790,7 +752,7 @@ void CallbackHandlers::DisableVerboseLoggingMethodCallback(const v8::FunctionCal
e.ReThrowToV8();
}
catch (std::exception e) {
stringstream ss;
stringstream ss;
ss << "Error: c++ exception: " << e.what() << endl;
NativeScriptException nsEx(ss.str());
nsEx.ReThrowToV8();
Expand Down Expand Up @@ -939,9 +901,9 @@ int CallbackHandlers::GetArrayLength(Isolate *isolate, const Local<Object>& arr)

jclass CallbackHandlers::RUNTIME_CLASS = nullptr;
jclass CallbackHandlers::JAVA_LANG_STRING = nullptr;
jfieldID CallbackHandlers::CURRENT_OBJECTID_FIELD_ID = nullptr;
jmethodID CallbackHandlers::RESOLVE_CLASS_METHOD_ID = nullptr;
jmethodID CallbackHandlers::CREATE_INSTANCE_METHOD_ID = nullptr;
jmethodID CallbackHandlers::CACHE_CONSTRUCTOR_METHOD_ID = nullptr;
jmethodID CallbackHandlers::MAKE_INSTANCE_STRONG_ID = nullptr;
jmethodID CallbackHandlers::GET_TYPE_METADATA = nullptr;
jmethodID CallbackHandlers::ENABLE_VERBOSE_LOGGING_METHOD_ID = nullptr;
jmethodID CallbackHandlers::DISABLE_VERBOSE_LOGGING_METHOD_ID = nullptr;
Expand Down
28 changes: 23 additions & 5 deletions src/jni/CallbackHandlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,13 @@ namespace tns

static v8::Local<v8::Object> CreateJSWrapper(v8::Isolate *isolate, jint javaObjectID, const std::string& typeName);

static jobject CreateJavaInstance(int objectID, const std::string& fullClassName, const ArgsWrapper& argWrapper, jclass javaClass, bool isInterface);

static bool RegisterInstance(v8::Isolate *isolate, const v8::Local<v8::Object>& jsObject, const std::string& fullClassName, const ArgsWrapper& argWrapper, const v8::Local<v8::Object>& implementationObject, bool isInterface);

static std::string ResolveConstructor(v8::Isolate *isolate, const ArgsWrapper& argWrapper, const std::string& fullClassName, jclass javaClass, bool isInterface);

static jclass ResolveClass(v8::Isolate *isolate, const std::string& fullClassname, const v8::Local<v8::Object>& implementationObject);

static std::string ResolveClassName(v8::Isolate *isolate, const std::string& fullClassname, const v8::Local<v8::Object>& implementationObject);
//

static v8::Local<v8::Value> GetArrayElement(v8::Isolate *isolate, const v8::Local<v8::Object>& array, uint32_t index, const std::string& arraySignature);

Expand Down Expand Up @@ -101,9 +100,9 @@ namespace tns

static jmethodID RESOLVE_CLASS_METHOD_ID;

static jmethodID CREATE_INSTANCE_METHOD_ID;
static jfieldID CURRENT_OBJECTID_FIELD_ID;

static jmethodID CACHE_CONSTRUCTOR_METHOD_ID;
static jmethodID MAKE_INSTANCE_STRONG_ID;

static jmethodID GET_TYPE_METADATA;

Expand All @@ -124,6 +123,25 @@ namespace tns
static std::map<std::string, int> s_constructorCache;

static std::map<std::string, jclass> s_classCache;

struct JavaObjectIdScope
{
JavaObjectIdScope(JEnv& env, jfieldID fieldId, jobject runtime, int javaObjectId)
: _env(env), _fieldID(fieldId), _runtime(runtime)
{
_env.SetIntField(_runtime, _fieldID, javaObjectId);
}

~JavaObjectIdScope()
{
_env.SetIntField(_runtime, _fieldID, -1);
}

private:
JEnv _env;
jfieldID _fieldID;
jobject _runtime;
};
};
}

Expand Down
7 changes: 7 additions & 0 deletions src/jni/JEnv.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ namespace tns

}

jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue *args)
{
jobject jo = m_env->NewObjectA(clazz, methodID, args);
CheckForJavaException();
return jo;
}

static void Init(JavaVM *jvm);

private:
Expand Down
Loading