diff --git a/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java b/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java
index c10715f58..215ac9301 100644
--- a/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java
+++ b/test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java
@@ -19,6 +19,8 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
 import fi.iki.elonen.NanoHTTPD;
 import fi.iki.elonen.NanoWSD;
 
@@ -27,14 +29,19 @@ class AndroidJsV8Inspector {
     private static String ApplicationDir;
     private String packageName;
 
+    @CriticalNative
     protected native final void init();
 
+    @FastNative
     protected native final void connect(Object connection);
 
+    @CriticalNative
     private native void scheduleBreak();
 
+    @CriticalNative
     protected static native void disconnect();
 
+    @FastNative
     protected native final void dispatchMessage(String message);
 
     private Handler mainHandler;
diff --git a/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.cpp b/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.cpp
index cdef52e62..03ce3bfa7 100644
--- a/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.cpp
+++ b/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.cpp
@@ -3,28 +3,42 @@
 #include <sstream>
 #include "JsV8InspectorClient.h"
 #include "ArgConverter.h"
+#include "com_tns_AndroidJsV8Inspector.h"
 
 using namespace tns;
 using namespace std;
 
-JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_init(JNIEnv* env, jobject object) {
-    JsV8InspectorClient::GetInstance()->init();
-}
 
-JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_connect(JNIEnv* env, jobject instance, jobject connection) {
+JNIEXPORT JNICALL void connect(JNIEnv *env, jobject instance, jobject connection) {
     JsV8InspectorClient::GetInstance()->disconnect();
     JsV8InspectorClient::GetInstance()->connect(connection);
 }
 
-JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_scheduleBreak(JNIEnv* env, jobject instance) {
+JNIEXPORT JNICALL void scheduleBreak(JNIEnv *env, jobject instance) {
     JsV8InspectorClient::GetInstance()->scheduleBreak();
 }
 
-JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_disconnect(JNIEnv* env, jobject instance) {
+JNIEXPORT JNICALL void scheduleBreakCritical() {
+    JsV8InspectorClient::GetInstance()->scheduleBreak();
+}
+
+JNIEXPORT JNICALL void disconnect(JNIEnv *env, jobject instance) {
+    JsV8InspectorClient::GetInstance()->disconnect();
+}
+
+JNIEXPORT JNICALL void disconnectCritical() {
     JsV8InspectorClient::GetInstance()->disconnect();
 }
 
-JNIEXPORT extern "C" void Java_com_tns_AndroidJsV8Inspector_dispatchMessage(JNIEnv* env, jobject instance, jstring jMessage) {
+JNIEXPORT JNICALL void dispatchMessage(JNIEnv *env, jobject instance, jstring jMessage) {
     std::string message = ArgConverter::jstringToString(jMessage);
     JsV8InspectorClient::GetInstance()->dispatchMessage(message);
 }
+
+JNIEXPORT JNICALL void init(JNIEnv *env, jobject object) {
+    JsV8InspectorClient::GetInstance()->init();
+}
+
+JNIEXPORT JNICALL void initCritical() {
+    JsV8InspectorClient::GetInstance()->init();
+}
diff --git a/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.h b/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.h
new file mode 100644
index 000000000..004e2099e
--- /dev/null
+++ b/test-app/runtime/src/main/cpp/com_tns_AndroidJsV8Inspector.h
@@ -0,0 +1,35 @@
+//
+// Created by Osei Fortune on 07/11/2023.
+//
+#include "jni.h"
+#include "JEnv.h"
+#include "NativeScriptException.h"
+#include <sstream>
+#include "JsV8InspectorClient.h"
+#include "ArgConverter.h"
+
+
+using namespace tns;
+using namespace std;
+
+#ifndef COM_TNS_ANDROIDJSV8INSPECTOR_H
+#define COM_TNS_ANDROIDJSV8INSPECTOR_H
+
+void init(JNIEnv *env, jobject object);
+
+void initCritical();
+
+void connect(JNIEnv *env, jobject instance, jobject connection);
+
+void scheduleBreak(JNIEnv *env, jobject instance);
+
+void scheduleBreakCritical();
+
+void disconnect(JNIEnv *env, jobject instance);
+
+void disconnectCritical();
+
+void dispatchMessage(JNIEnv *env, jobject instance, jstring jMessage);
+
+
+#endif //COM_TNS_ANDROIDJSV8INSPECTOR_H
diff --git a/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.cpp b/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.cpp
index f65609639..940a9761e 100644
--- a/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.cpp
+++ b/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.cpp
@@ -7,7 +7,7 @@
 using namespace tns;
 using namespace std;
 
-extern "C" JNIEXPORT void Java_com_tns_AssetExtractor_extractAssets(JNIEnv* env, jobject obj, jstring apk, jstring inputDir, jstring outputDir, jboolean _forceOverwrite) {
+JNIEXPORT JNICALL void extractAssets(JNIEnv* env, jobject obj, jstring apk, jstring inputDir, jstring outputDir, jboolean _forceOverwrite) {
     try {
         AssetExtractor::ExtractAssets(env, obj, apk, inputDir, outputDir, _forceOverwrite);
     } catch (NativeScriptException& e) {
diff --git a/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.h b/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.h
new file mode 100644
index 000000000..60540dc38
--- /dev/null
+++ b/test-app/runtime/src/main/cpp/com_tns_AssetExtractor.h
@@ -0,0 +1,19 @@
+//
+// Created by Osei Fortune on 07/11/2023.
+//
+
+#include "jni.h"
+#include "AssetExtractor.h"
+#include "NativeScriptException.h"
+
+#include <sstream>
+
+#ifndef COM_TNS_ASSETEXTRACTOR_H
+#define COM_TNS_ASSETEXTRACTOR_H
+
+using namespace std;
+using namespace tns;
+
+void extractAssets(JNIEnv* env, jobject obj, jstring apk, jstring inputDir, jstring outputDir, jboolean _forceOverwrite);
+
+#endif //COM_TNS_ASSETEXTRACTOR_H
diff --git a/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp b/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
index 01777f9ab..fb5449baa 100644
--- a/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
+++ b/test-app/runtime/src/main/cpp/com_tns_Runtime.cpp
@@ -3,29 +3,35 @@
 #include "NativeScriptException.h"
 #include "CallbackHandlers.h"
 #include <sstream>
-
+#include "com_tns_AssetExtractor.h"
+#include "com_tns_AndroidJsV8Inspector.h"
 using namespace std;
 using namespace tns;
 
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
-    try {
-        Runtime::Init(vm, reserved);
-    } catch (NativeScriptException& e) {
-        e.ReThrowToJava();
-    } catch (std::exception e) {
-        stringstream ss;
-        ss << "Error: c++ exception: " << e.what() << endl;
-        NativeScriptException nsEx(ss.str());
-        nsEx.ReThrowToJava();
-    } catch (...) {
-        NativeScriptException nsEx(std::string("Error: c++ exception!"));
-        nsEx.ReThrowToJava();
+#define ANDROID_O 26
+
+int getApiVersion(JNIEnv *env) {
+    jint sdkInt = -1;
+    bool success = true;
+    jclass versionClass = env->FindClass("android/os/Build$VERSION");
+
+    if (versionClass == nullptr) {
+        success = false;
     }
 
-    return JNI_VERSION_1_6;
+    jfieldID sdkIntFieldID;
+    if (success) {
+        success = ((sdkIntFieldID = env->GetStaticFieldID(versionClass, "SDK_INT", "I")) != nullptr);
+    }
+
+    if (success) {
+        sdkInt = env->GetStaticIntField(versionClass, sdkIntFieldID);
+    }
+
+    return sdkInt;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationMode(JNIEnv* _env, jobject obj, jstring mode) {
+static JNICALL void SetManualInstrumentationMode(JNIEnv* _env, jclass _clazz, jstring mode) {
     try {
         Runtime::SetManualInstrumentationMode(mode);
     } catch (...) {
@@ -34,7 +40,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_SetManualInstrumentationMode(JNIE
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_initNativeScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring filesPath, jstring nativeLibDir, jboolean verboseLoggingEnabled, jboolean isDebuggable, jstring packageName, jobjectArray args, jstring callingDir, jint maxLogcatObjectSize, jboolean forceLog) {
+static JNICALL void initNativeScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring filesPath, jstring nativeLibDir, jboolean verboseLoggingEnabled, jboolean isDebuggable, jstring packageName, jobjectArray args, jstring callingDir, jint maxLogcatObjectSize, jboolean forceLog) {
     try {
         Runtime::Init(_env, obj, runtimeId, filesPath, nativeLibDir, verboseLoggingEnabled, isDebuggable, packageName, args, callingDir, maxLogcatObjectSize, forceLog);
     } catch (NativeScriptException& e) {
@@ -68,7 +74,7 @@ Runtime* TryGetRuntime(int runtimeId) {
     return runtime;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_runModule(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
+static JNICALL void runModule(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return;
@@ -96,7 +102,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_runModule(JNIEnv* _env, jobject o
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_runWorker(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
+static  JNICALL void runWorker(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return;
@@ -124,7 +130,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_runWorker(JNIEnv* _env, jobject o
     }
 }
 
-extern "C" JNIEXPORT jobject Java_com_tns_Runtime_runScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
+static JNICALL jobject runScript(JNIEnv* _env, jobject obj, jint runtimeId, jstring scriptFile) {
     jobject result = nullptr;
 
     auto runtime = TryGetRuntime(runtimeId);
@@ -155,7 +161,7 @@ extern "C" JNIEXPORT jobject Java_com_tns_Runtime_runScript(JNIEnv* _env, jobjec
     return result;
 }
 
-extern "C" JNIEXPORT jobject Java_com_tns_Runtime_callJSMethodNative(JNIEnv* _env, jobject obj, jint runtimeId, jint javaObjectID, jstring methodName, jint retType, jboolean isConstructor, jobjectArray packagedArgs) {
+static JNICALL jobject callJSMethodNative(JNIEnv* _env, jobject obj, jint runtimeId, jint javaObjectID, jstring methodName, jint retType, jboolean isConstructor, jobjectArray packagedArgs) {
     jobject result = nullptr;
 
     auto runtime = TryGetRuntime(runtimeId);
@@ -186,7 +192,7 @@ extern "C" JNIEXPORT jobject Java_com_tns_Runtime_callJSMethodNative(JNIEnv* _en
     return result;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_createJSInstanceNative(JNIEnv* _env, jobject obj, jint runtimeId, jobject javaObject, jint javaObjectID, jstring className) {
+static JNICALL void createJSInstanceNative(JNIEnv* _env, jobject obj, jint runtimeId, jobject javaObject, jint javaObjectID, jstring className) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return;
@@ -214,7 +220,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_createJSInstanceNative(JNIEnv* _e
     }
 }
 
-extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(JNIEnv* env, jobject obj, jint runtimeId) {
+static JNICALL jint generateNewObjectId(JNIEnv* env, jobject obj, jint runtimeId) {
     try {
         auto runtime = TryGetRuntime(runtimeId);
         if (runtime == nullptr) {
@@ -236,7 +242,8 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_generateNewObjectId(JNIEnv* env,
     return 0;
 }
 
-extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* env, jobject obj, jint runtimeId) {
+
+static JNICALL jboolean notifyGc(JNIEnv* env, jobject obj, jint runtimeId) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return JNI_FALSE;
@@ -246,21 +253,21 @@ extern "C" JNIEXPORT jboolean Java_com_tns_Runtime_notifyGc(JNIEnv* env, jobject
     return success;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_lock(JNIEnv* env, jobject obj, jint runtimeId) {
+static JNICALL void rtLock(JNIEnv* env, jobject obj, jint runtimeId) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime != nullptr) {
         runtime->Lock();
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_unlock(JNIEnv* env, jobject obj, jint runtimeId) {
+static JNICALL void rtUnlock(JNIEnv* env, jobject obj, jint runtimeId) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime != nullptr) {
         runtime->Unlock();
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* env, jobject obj, jint runtimeId, jthrowable exception, jstring message, jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded) {
+static JNICALL void passExceptionToJsNative(JNIEnv* env, jobject obj, jint runtimeId, jthrowable exception, jstring message, jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return;
@@ -288,11 +295,11 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* e
     }
 }
 
-extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSize(JNIEnv* env, jobject obj) {
+static JNICALL jint getPointerSize(JNIEnv* env, jobject obj) {
     return sizeof(void*);
 }
 
-extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeId(JNIEnv* _env, jobject obj) {
+static JNICALL jint getCurrentRuntimeId(JNIEnv* _env, jobject obj) {
     Isolate* isolate = Isolate::TryGetCurrent();
     if (isolate == nullptr) {
         return -1;
@@ -303,7 +310,7 @@ extern "C" JNIEXPORT jint Java_com_tns_Runtime_getCurrentRuntimeId(JNIEnv* _env,
     return id;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerGlobalOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jstring msg) {
+static JNICALL void WorkerGlobalOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jstring msg) {
     // Worker Thread runtime
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
@@ -321,7 +328,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerGlobalOnMessageCallback(JNI
     CallbackHandlers::WorkerGlobalOnMessageCallback(isolate, msg);
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerObjectOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring msg) {
+static JNICALL void WorkerObjectOnMessageCallback(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring msg) {
     // Main Thread runtime
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
@@ -339,7 +346,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_WorkerObjectOnMessageCallback(JNI
     CallbackHandlers::WorkerObjectOnMessageCallback(isolate, workerId, msg);
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_TerminateWorkerCallback(JNIEnv* env, jobject obj, jint runtimeId) {
+static JNICALL void TerminateWorkerCallback(JNIEnv* env, jobject obj, jint runtimeId) {
     // Worker Thread runtime
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
@@ -363,7 +370,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_TerminateWorkerCallback(JNIEnv* e
     delete runtime;
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_ClearWorkerPersistent(JNIEnv* env, jobject obj, jint runtimeId, jint workerId) {
+static JNICALL void ClearWorkerPersistent(JNIEnv* env, jobject obj, jint runtimeId, jint workerId) {
     // Worker Thread runtime
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
@@ -381,7 +388,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_ClearWorkerPersistent(JNIEnv* env
     CallbackHandlers::ClearWorkerPersistent(workerId);
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_CallWorkerObjectOnErrorHandleMain(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring message, jstring stackTrace, jstring filename, jint lineno, jstring threadName) {
+static JNICALL void CallWorkerObjectOnErrorHandleMain(JNIEnv* env, jobject obj, jint runtimeId, jint workerId, jstring message, jstring stackTrace, jstring filename, jint lineno, jstring threadName) {
     // Main Thread runtime
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
@@ -402,7 +409,7 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_CallWorkerObjectOnErrorHandleMain
     }
 }
 
-extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(JNIEnv* _env, jobject obj, jint runtimeId) {
+static JNICALL void ResetDateTimeConfigurationCache(JNIEnv* _env, jobject obj, jint runtimeId) {
     auto runtime = TryGetRuntime(runtimeId);
     if (runtime == nullptr) {
         return;
@@ -410,4 +417,195 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_ResetDateTimeConfigurationCache(J
 
     auto isolate = runtime->GetIsolate();
     isolate->DateTimeConfigurationChangeNotification(Isolate::TimeZoneDetection::kRedetect);
+}
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
+    try {
+
+        JNIEnv *env;
+        if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
+            return JNI_ERR;
+        }
+
+        int apiVersion = getApiVersion(env);
+
+        if (apiVersion == -1) {
+            __android_log_write(ANDROID_LOG_ERROR, "JS", "Could not get Android API version!");
+            return JNI_ERR;
+        }
+
+        jint result;
+
+
+
+
+        if (apiVersion >= ANDROID_O) {
+            // Redirect func_bangJni to fastNativeFunc since !bang JNI is not supported anymore
+            JNINativeMethod methodsInternal[] = {
+                    { "SetManualInstrumentationMode", "(Ljava/lang/String;)V", (void *) SetManualInstrumentationMode },
+                    { "initNativeScript", "(ILjava/lang/String;Ljava/lang/String;ZZLjava/lang/String;[Ljava/lang/Object;Ljava/lang/String;IZ)V", (void *) initNativeScript },
+                    { "runModule", "(ILjava/lang/String;)V", (void *) runModule },
+                    { "runWorker", "(ILjava/lang/String;)V", (void *) runWorker },
+                    { "runScript", "(ILjava/lang/String;)Ljava/lang/Object;", (void *) runScript },
+                    { "callJSMethodNative", "(IILjava/lang/String;IZ[Ljava/lang/Object;)Ljava/lang/Object;", (void *) callJSMethodNative },
+                    { "createJSInstanceNative", "(ILjava/lang/Object;ILjava/lang/String;)V", (void *) createJSInstanceNative },
+                    { "generateNewObjectId", "(I)I", (void *) generateNewObjectId },
+                    { "notifyGc", "(I)Z", (void *) notifyGc },
+                    { "lock", "(I)V", (void *) rtLock },
+                    { "unlock", "(I)V", (void *) rtUnlock },
+                    { "passExceptionToJsNative", "(ILjava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", (void *) passExceptionToJsNative },
+                    { "getPointerSize", "()I", (void *) getPointerSize },
+                    { "getCurrentRuntimeId", "()I", (void *) getCurrentRuntimeId },
+                    { "WorkerGlobalOnMessageCallback", "(ILjava/lang/String;)V", (void *) WorkerGlobalOnMessageCallback },
+                    { "WorkerObjectOnMessageCallback", "(IILjava/lang/String;)V", (void *) WorkerObjectOnMessageCallback },
+                    { "TerminateWorkerCallback", "(I)V", (void *) TerminateWorkerCallback },
+                    { "ClearWorkerPersistent", "(II)V", (void *) ClearWorkerPersistent },
+                    { "CallWorkerObjectOnErrorHandleMain", "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V", (void *) CallWorkerObjectOnErrorHandleMain },
+                    { "ResetDateTimeConfigurationCache", "(I)V", (void *) ResetDateTimeConfigurationCache },
+            };
+
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/Runtime"),
+                    methodsInternal,
+                    sizeof(methodsInternal) / sizeof(JNINativeMethod));
+
+
+            if (result != JNI_OK) {
+                __android_log_print(ANDROID_LOG_ERROR, "JS", "Error code %d when registering native functions!",
+                                    result);
+                return JNI_ERR;
+            }
+
+
+            JNINativeMethod assetMethodsInternal[] = {
+                    { "extractAssets", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", (void *) extractAssets }
+            };
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/AssetExtractor"),
+                    assetMethodsInternal,
+                    sizeof(assetMethodsInternal) / sizeof(JNINativeMethod));
+
+
+
+            if (result != JNI_OK) {
+                __android_log_print(ANDROID_LOG_ERROR, "JS", "Error code %d when registering native functions!",
+                                    result);
+                return JNI_ERR;
+            }
+
+
+            JNINativeMethod inspectorMethodsInternal[] = {
+                    { "init", "()V", (void *) initCritical },
+                    { "connect", "(Ljava/lang/Object;)V", (void *) connect },
+                    { "scheduleBreak", "()V", (void *) scheduleBreakCritical },
+                    { "disconnect", "()V", (void *) disconnectCritical },
+                    { "dispatchMessage", "(Ljava/lang/String;)V", (void *) dispatchMessage }
+            };
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/AndroidJsV8Inspector"),
+                    inspectorMethodsInternal,
+                    sizeof(inspectorMethodsInternal) / sizeof(JNINativeMethod));
+
+
+        }
+        else {
+            // Redirect CriticalNative function to !bang JNI function (need JNIEnv and jclass on Android 7-)
+            // !bang JNI notation used to demonstrate faster calls on Android 7-
+            JNINativeMethod methodsInternal[] = {
+                    { "SetManualInstrumentationMode", "!(Ljava/lang/String;)V", (void *) SetManualInstrumentationMode },
+                    { "initNativeScript", "!(ILjava/lang/String;Ljava/lang/String;ZZLjava/lang/String;[Ljava/lang/Object;Ljava/lang/String;IZ)V", (void *) initNativeScript },
+                    { "runModule", "!(ILjava/lang/String;)V", (void *) runModule },
+                    { "runWorker", "!(ILjava/lang/String;)V", (void *) runWorker },
+                    { "runScript", "!(ILjava/lang/String;)Ljava/lang/Object;", (void *) runScript },
+                    { "callJSMethodNative", "!(IILjava/lang/String;IZ[Ljava/lang/Object;)Ljava/lang/Object;", (void *) callJSMethodNative },
+                    { "createJSInstanceNative", "!(ILjava/lang/Object;ILjava/lang/String;)V", (void *) createJSInstanceNative },
+                    { "generateNewObjectId", "!(I)I", (void *) generateNewObjectId },
+                    { "notifyGc", "!(I)Z", (void *) notifyGc },
+                    { "lock", "!(I)V", (void *) rtLock },
+                    { "unlock", "!(I)V", (void *) rtUnlock },
+                    { "passExceptionToJsNative", "!(ILjava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", (void *) passExceptionToJsNative },
+                    { "getPointerSize", "!()I", (void *) getPointerSize },
+                    { "getCurrentRuntimeId", "!()I", (void *) getCurrentRuntimeId },
+                    { "WorkerGlobalOnMessageCallback", "!(ILjava/lang/String;)V", (void *) WorkerGlobalOnMessageCallback },
+                    { "WorkerObjectOnMessageCallback", "!(IILjava/lang/String;)V", (void *) WorkerObjectOnMessageCallback },
+                    { "TerminateWorkerCallback", "!(I)V", (void *) TerminateWorkerCallback },
+                    { "ClearWorkerPersistent", "!(II)V", (void *) ClearWorkerPersistent },
+                    { "CallWorkerObjectOnErrorHandleMain", "!(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V", (void *) CallWorkerObjectOnErrorHandleMain },
+                    { "ResetDateTimeConfigurationCache", "!(I)V", (void *) ResetDateTimeConfigurationCache },
+            };
+
+
+
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/Runtime"),
+                    methodsInternal,
+                    sizeof(methodsInternal) / sizeof(JNINativeMethod));
+
+
+
+
+            if (result != JNI_OK) {
+                __android_log_print(ANDROID_LOG_ERROR, "JS", "Error code %d when registering native functions!",
+                                    result);
+                return JNI_ERR;
+            }
+
+
+            JNINativeMethod assetMethodsInternal[] = {
+                    { "extractAssets", "!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", (void *) extractAssets }
+            };
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/AssetExtractor"),
+                    assetMethodsInternal,
+                    sizeof(assetMethodsInternal) / sizeof(JNINativeMethod));
+
+
+            if (result != JNI_OK) {
+                __android_log_print(ANDROID_LOG_ERROR, "JS", "Error code %d when registering native functions!",
+                                    result);
+                return JNI_ERR;
+            }
+
+
+            JNINativeMethod inspectorMethodsInternal[] = {
+                    { "init", "!()V", (void *) init },
+                    { "connect", "!(Ljava/lang/Object;)V", (void *) connect },
+                    { "scheduleBreak", "!()V", (void *) scheduleBreak },
+                    { "disconnect", "!()V", (void *) disconnect },
+                    { "dispatchMessage", "!(Ljava/lang/String;)V", (void *) dispatchMessage }
+            };
+
+            result = env->RegisterNatives(
+                    env->FindClass("com/tns/AndroidJsV8Inspector"),
+                    inspectorMethodsInternal,
+                    sizeof(inspectorMethodsInternal) / sizeof(JNINativeMethod));
+
+        }
+
+        if (result != JNI_OK) {
+            __android_log_print(ANDROID_LOG_ERROR, "JS", "Error code %d when registering native functions!",
+                                result);
+            return JNI_ERR;
+        }
+
+
+        Runtime::Init(vm, reserved);
+    } catch (NativeScriptException& e) {
+        e.ReThrowToJava();
+    } catch (std::exception e) {
+        stringstream ss;
+        ss << "Error: c++ exception: " << e.what() << endl;
+        NativeScriptException nsEx(ss.str());
+        nsEx.ReThrowToJava();
+    } catch (...) {
+        NativeScriptException nsEx(std::string("Error: c++ exception!"));
+        nsEx.ReThrowToJava();
+    }
+
+    return JNI_VERSION_1_6;
 }
\ No newline at end of file
diff --git a/test-app/runtime/src/main/java/com/tns/AssetExtractor.java b/test-app/runtime/src/main/java/com/tns/AssetExtractor.java
index 9ebf966aa..466ed6e47 100644
--- a/test-app/runtime/src/main/java/com/tns/AssetExtractor.java
+++ b/test-app/runtime/src/main/java/com/tns/AssetExtractor.java
@@ -6,7 +6,10 @@
 import android.content.Context;
 import android.util.Log;
 
+import dalvik.annotation.optimization.FastNative;
+
 public class AssetExtractor {
+    @FastNative
     private native void extractAssets(String apkPath, String input, String outputDir, boolean checkForNewerFiles);
     private final Logger logger;
 
diff --git a/test-app/runtime/src/main/java/com/tns/Runtime.java b/test-app/runtime/src/main/java/com/tns/Runtime.java
index ad8caed91..a265abd20 100644
--- a/test-app/runtime/src/main/java/com/tns/Runtime.java
+++ b/test-app/runtime/src/main/java/com/tns/Runtime.java
@@ -36,46 +36,69 @@
 import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
 public class Runtime {
+    @FastNative
     private native void initNativeScript(int runtimeId, String filesPath, String nativeLibDir, boolean verboseLoggingEnabled, boolean isDebuggable, String packageName,
                                          Object[] v8Options, String callingDir, int maxLogcatObjectSize, boolean forceLog);
 
+    @FastNative
     private native void runModule(int runtimeId, String filePath) throws NativeScriptException;
 
+    @FastNative
     private native void runWorker(int runtimeId, String filePath) throws NativeScriptException;
 
+    @FastNative
     private native Object runScript(int runtimeId, String filePath) throws NativeScriptException;
 
+    @FastNative
     private native Object callJSMethodNative(int runtimeId, int javaObjectID, String methodName, int retType, boolean isConstructor, Object... packagedArgs) throws NativeScriptException;
 
+    @FastNative
     private native void createJSInstanceNative(int runtimeId, Object javaObject, int javaObjectID, String canonicalName);
 
+    @FastNative
     private native int generateNewObjectId(int runtimeId);
 
+    @FastNative
     private native boolean notifyGc(int runtimeId);
 
+    @FastNative
     private native void lock(int runtimeId);
 
+    @FastNative
     private native void unlock(int runtimeId);
 
+    @FastNative
     private native void passExceptionToJsNative(int runtimeId, Throwable ex, String message, String fullStackTrace, String jsStackTrace, boolean isDiscarded);
 
+    @FastNative
     private static native int getCurrentRuntimeId();
 
+    @FastNative
     public static native int getPointerSize();
 
+    @FastNative
     public static native void SetManualInstrumentationMode(String mode);
 
+    @FastNative
     private static native void WorkerGlobalOnMessageCallback(int runtimeId, String message);
 
+    @FastNative
     private static native void WorkerObjectOnMessageCallback(int runtimeId, int workerId, String message);
 
+    @FastNative
     private static native void TerminateWorkerCallback(int runtimeId);
 
+    @FastNative
     private static native void ClearWorkerPersistent(int runtimeId, int workerId);
 
+    @FastNative
     private static native void CallWorkerObjectOnErrorHandleMain(int runtimeId, int workerId, String message, String stackTrace, String filename, int lineno, String threadName) throws NativeScriptException;
 
+    @FastNative
     private static native void ResetDateTimeConfigurationCache(int runtimeId);
 
     void passUncaughtExceptionToJs(Throwable ex, String message, String fullStackTrace, String jsStackTrace) {
diff --git a/test-app/runtime/src/main/java/dalvik/annotation/optimization/CriticalNative.java b/test-app/runtime/src/main/java/dalvik/annotation/optimization/CriticalNative.java
new file mode 100644
index 000000000..672cd1703
--- /dev/null
+++ b/test-app/runtime/src/main/java/dalvik/annotation/optimization/CriticalNative.java
@@ -0,0 +1,10 @@
+package dalvik.annotation.optimization;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)  // Save memory, don't instantiate as an object at runtime.
+@Target(ElementType.METHOD)
+public @interface CriticalNative {}
\ No newline at end of file
diff --git a/test-app/runtime/src/main/java/dalvik/annotation/optimization/FastNative.java b/test-app/runtime/src/main/java/dalvik/annotation/optimization/FastNative.java
new file mode 100644
index 000000000..bb519e7f9
--- /dev/null
+++ b/test-app/runtime/src/main/java/dalvik/annotation/optimization/FastNative.java
@@ -0,0 +1,11 @@
+package dalvik.annotation.optimization;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD})
+public @interface FastNative {
+}
\ No newline at end of file