Skip to content

Commit 73dc8c3

Browse files
author
Mihail Slavchev
authored
Merge pull request #495 from NativeScript/slavchev/fix-issue-476
Fix for #476. For some throwable object getStackTrace() method throws…
2 parents 17965f2 + 6497dda commit 73dc8c3

8 files changed

Lines changed: 62 additions & 67 deletions

File tree

runtime/src/main/java/com/tns/NativeScriptException.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,30 @@ public NativeScriptException(String detailMessage, long jsValueAddress)
3030
super(detailMessage);
3131
this.jsValueAddress = jsValueAddress;
3232
}
33+
34+
@RuntimeCallable
35+
public static String getStackTraceAsString(Throwable ex)
36+
{
37+
String errMessage;
38+
try
39+
{
40+
errMessage = ex.toString();
41+
for (StackTraceElement frame: ex.getStackTrace())
42+
{
43+
errMessage += "\n ";
44+
errMessage += frame;
45+
}
46+
47+
Throwable cause = ex.getCause();
48+
if (cause != null) {
49+
errMessage += "\nCaused by: ";
50+
errMessage += getStackTraceAsString(cause);
51+
}
52+
}
53+
catch (Throwable err)
54+
{
55+
errMessage = "Unknown error. Cannot get error message.";
56+
}
57+
return errMessage;
58+
}
3359
}

runtime/src/main/jni/NativeScriptException.cpp

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,6 @@ void NativeScriptException::Init(ObjectManager *objectManager)
135135
THROWABLE_CLASS = env.FindClass("java/lang/Throwable");
136136
assert(THROWABLE_CLASS != nullptr);
137137

138-
THROWABLE_GET_CAUSE_METHOD_ID = env.GetMethodID(THROWABLE_CLASS, "getCause", "()Ljava/lang/Throwable;");
139-
assert(THROWABLE_GET_CAUSE_METHOD_ID != nullptr);
140-
141-
THROWABLE_GET_STACK_TRACE_METHOD_ID = env.GetMethodID(THROWABLE_CLASS, "getStackTrace", "()[Ljava/lang/StackTraceElement;");
142-
assert(THROWABLE_GET_STACK_TRACE_METHOD_ID != nullptr);
143-
144-
THROWABLE_TO_STRING_METHOD_ID = env.GetMethodID(THROWABLE_CLASS, V8StringConstants::TO_STRING, "()Ljava/lang/String;");
145-
assert(THROWABLE_TO_STRING_METHOD_ID != nullptr);
146-
147-
STACK_TRACE_ELEMENT_CLASS = env.FindClass("java/lang/StackTraceElement");
148-
assert(STACK_TRACE_ELEMENT_CLASS != nullptr);
149-
150-
FRAME_TO_STRING_METHOD_ID = env.GetMethodID(STACK_TRACE_ELEMENT_CLASS, V8StringConstants::TO_STRING, "()Ljava/lang/String;");
151-
assert(FRAME_TO_STRING_METHOD_ID != nullptr);
152-
153138
NATIVESCRIPTEXCEPTION_CLASS = env.FindClass("com/tns/NativeScriptException");
154139
assert(NATIVESCRIPTEXCEPTION_CLASS != nullptr);
155140

@@ -158,6 +143,9 @@ void NativeScriptException::Init(ObjectManager *objectManager)
158143

159144
NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID = env.GetMethodID(NATIVESCRIPTEXCEPTION_CLASS, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
160145
assert(NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID != nullptr);
146+
147+
NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID = env.GetStaticMethodID(NATIVESCRIPTEXCEPTION_CLASS, "getStackTraceAsString", "(Ljava/lang/Throwable;)Ljava/lang/String;");
148+
assert(NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID != nullptr);
161149
}
162150

163151
// ON V8 UNCAUGHT EXCEPTION
@@ -394,62 +382,21 @@ string NativeScriptException::GetErrorStackTrace(const Local<StackTrace>& stackT
394382
string NativeScriptException::GetExceptionMessage(JEnv& env, jthrowable exception)
395383
{
396384
string errMsg;
397-
JniLocalRef frames(env.CallObjectMethod(exception, THROWABLE_GET_STACK_TRACE_METHOD_ID));
398-
399-
jsize framesLength = env.GetArrayLength(frames);
400-
401-
if (nullptr != (jobjectArray) frames)
402-
{
403-
JniLocalRef msg(env.CallObjectMethod(exception, THROWABLE_TO_STRING_METHOD_ID));
404-
405-
const char* msgStr = env.GetStringUTFChars(msg, nullptr);
406-
407-
if (!errMsg.empty())
408-
{
409-
errMsg.append("\nCaused by: ");
410-
errMsg.append(msgStr);
411-
}
412-
else
413-
{
414-
errMsg = msgStr;
415-
}
385+
JniLocalRef msg(env.CallStaticObjectMethod(NATIVESCRIPTEXCEPTION_CLASS, NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID, exception));
416386

417-
env.ReleaseStringUTFChars(msg, msgStr);
418-
}
387+
const char* msgStr = env.GetStringUTFChars(msg, nullptr);
419388

420-
for (jsize i = 0; i < framesLength; i++)
421-
{
422-
JniLocalRef frame(env.GetObjectArrayElement(frames, i));
423-
JniLocalRef msg(env.CallObjectMethod(frame, FRAME_TO_STRING_METHOD_ID));
424-
425-
const char* msgStr = env.GetStringUTFChars(msg, nullptr);
389+
errMsg.append(msgStr);
426390

427-
errMsg.append("\n ");
428-
errMsg.append(msgStr);
391+
env.ReleaseStringUTFChars(msg, msgStr);
429392

430-
env.ReleaseStringUTFChars(msg, msgStr);
431-
}
432-
433-
if (nullptr != (jobjectArray) frames)
434-
{
435-
JniLocalRef cause(env.CallObjectMethod(exception, THROWABLE_GET_CAUSE_METHOD_ID));
436-
437-
if (nullptr != (jthrowable) cause)
438-
{
439-
errMsg = GetExceptionMessage(env, cause);
440-
}
441-
}
442393
return errMsg;
443394
}
444395

445396
ObjectManager* NativeScriptException::objectManager = nullptr;
446397
jclass NativeScriptException::RUNTIME_CLASS = nullptr;
447398
jclass NativeScriptException::THROWABLE_CLASS = nullptr;
448-
jmethodID NativeScriptException::THROWABLE_GET_CAUSE_METHOD_ID = nullptr;
449-
jmethodID NativeScriptException::THROWABLE_GET_STACK_TRACE_METHOD_ID = nullptr;
450-
jmethodID NativeScriptException::THROWABLE_TO_STRING_METHOD_ID = nullptr;
451-
jclass NativeScriptException::STACK_TRACE_ELEMENT_CLASS = nullptr;
452-
jmethodID NativeScriptException::FRAME_TO_STRING_METHOD_ID = nullptr;
453399
jclass NativeScriptException::NATIVESCRIPTEXCEPTION_CLASS = nullptr;
454400
jmethodID NativeScriptException::NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID = nullptr;
455401
jmethodID NativeScriptException::NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID = nullptr;
402+
jmethodID NativeScriptException::NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID = nullptr;

runtime/src/main/jni/NativeScriptException.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,10 @@ namespace tns
4040
static ObjectManager *objectManager;
4141
static jclass RUNTIME_CLASS;
4242
static jclass THROWABLE_CLASS;
43-
static jmethodID THROWABLE_GET_CAUSE_METHOD_ID;
44-
static jmethodID THROWABLE_GET_STACK_TRACE_METHOD_ID;
45-
static jmethodID THROWABLE_TO_STRING_METHOD_ID;
46-
static jclass STACK_TRACE_ELEMENT_CLASS;
47-
static jmethodID FRAME_TO_STRING_METHOD_ID;
4843
static jclass NATIVESCRIPTEXCEPTION_CLASS;
4944
static jmethodID NATIVESCRIPTEXCEPTION_JSVALUE_CTOR_ID;
5045
static jmethodID NATIVESCRIPTEXCEPTION_THROWABLE_CTOR_ID;
46+
static jmethodID NATIVESCRIPTEXCEPTION_GET_STACK_TRACE_AS_STRING_METHOD_ID;
5147
};
5248
}
5349

test-app/app/src/main/assets/app/tests/exceptionHandlingTests.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ describe("Tests exception handling ", function () {
280280
}
281281

282282
expect(exceptionCaught).toBe(true);
283-
284283
});
285284

286285
it("should not wrap the thrown exception into NativeScriptException", function () {
@@ -311,4 +310,17 @@ describe("Tests exception handling ", function () {
311310
expect(e2.getCause().getClass()).toBe(java.io.IOException.class);
312311
});
313312

313+
it("should successfully catch Java exception when getStackTrace fails", function () {
314+
var test = new com.tns.tests.ExceptionHandlingTest();
315+
var exceptionCaught = false;
316+
var errMsg;
317+
try {
318+
test.throwException();
319+
} catch (e) {
320+
exceptionCaught = true;
321+
errMsg = e.toString();
322+
}
323+
expect(exceptionCaught).toBe(true);
324+
expect(errMsg).toBe("Error: Unknown error. Cannot get error message.");
325+
});
314326
});
-7.71 KB
Binary file not shown.
21 KB
Binary file not shown.
-44.4 KB
Binary file not shown.

test-app/app/src/main/java/com/tns/tests/ExceptionHandlingTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77

88
public class ExceptionHandlingTest
99
{
10+
private static class BadException extends Exception
11+
{
12+
public BadException() {}
13+
14+
@Override
15+
public StackTraceElement[] getStackTrace() {
16+
throw new RuntimeException();
17+
}
18+
}
19+
1020
public void triggerEvent1(String s, int n) throws Exception
1121
{
1222
this.onEvent1(s, n);
@@ -51,4 +61,8 @@ public void getExceptionRec(String s, int n)
5161
{
5262
this.onGetFile(s, n);
5363
}
64+
65+
public void throwException() throws BadException {
66+
throw new BadException();
67+
}
5468
}

0 commit comments

Comments
 (0)