title: JNI - crash on NewObjectArray
body: <p>I have this code:</p>
  
  <p>Wrapper for JNI calls:</p>
  
  <pre><code>/// &lt;summary&gt;
  /// Simple JNI class wrapper
  /// &lt;/summary&gt;
  struct SimpleJNIClass{
      JavaVM* vm = nullptr;
      jobject instanceRef = nullptr;
      JNIEnv *lockedEnv = nullptr;
  
      SimpleJNIClass(JNIEnv *env, jobject instanceRef){
          //Returns the Java VM interface (used in the Invocation API) associated with the current thread.
          //The result is placed at the location pointed to by the second argument, vm.
          env-&gt;GetJavaVM(&amp;this-&gt;vm);
          this-&gt;instanceRef = (jobject)env-&gt;NewGlobalRef(instanceRef);
      };
  
      SimpleJNIClass(JNIEnv * env){
          env-&gt;GetJavaVM(&amp;this-&gt;vm);
      };
  
      virtual ~SimpleJNIClass() {
          if (this-&gt;vm == nullptr) {
              return;
          }
  
          if (JNIEnv * env = GetEnv()){
              env-&gt;DeleteGlobalRef(instanceRef);
              instanceRef = nullptr;
              FreeEnv(env);
          }
      };
  
  
      JNIEnv * LockEnv() {
          this-&gt;lockedEnv = this-&gt;GetEnv();
  
          return this-&gt;lockedEnv;
      }
  
      void UnLockEnv() {
          this-&gt;lockedEnv = nullptr;
          this-&gt;FreeEnv(this-&gt;lockedEnv);
      }
  
      JNIEnv * GetEnv(){
          if (this-&gt;lockedEnv != nullptr) {
              return this-&gt;lockedEnv;
          }
  
          JNIEnv * env = nullptr;
          int getEnvStat = vm-&gt;GetEnv((void **)&amp;env, JNI_VERSION_1_4);
  
          if (getEnvStat == JNI_EDETACHED){
              if (vm-&gt;AttachCurrentThread(&amp;env, NULL) != 0){
                  MY_LOG_ERROR("AttachCurrentThread was not successful. "
                      "This may be due to the thread being attached already to another JVM instance.");
              }
              else{
                  attachCurrentThread = true;
              }
          }
          else if (getEnvStat == JNI_OK){
              //no need to attach, already attached
          }
          else if (getEnvStat == JNI_EVERSION){
              MY_LOG_ERROR("GetEnv: version not supported");
          }
  
          return env;
      };
  
      void FreeEnv(JNIEnv * env) {
          if (this-&gt;lockedEnv != nullptr) {
              return;
          }
          if (attachCurrentThread) {
              vm-&gt;DetachCurrentThread();
              attachCurrentThread = false;
          }
      }
  
  protected:
      bool attachCurrentThread = false;
  };
  
  
  struct JNICallback : public SimpleJNIClass
  {
  
      jmethodID callbackMethod = nullptr;
  
      JNICallback(JNIEnv *env, jobject classRef,
          const std::string &amp; methodName, const std::string &amp; methodSignature)
          : SimpleJNIClass(env, classRef) {
          jclass callbackClass = (jclass)env-&gt;GetObjectClass(this-&gt;instanceRef);
          this-&gt;callbackMethod = env-&gt;GetMethodID(callbackClass, methodName.c_str(), methodSignature.c_str());
      };
  
      virtual ~JNICallback() {
          callbackMethod = nullptr;
      }
  
      template&lt;typename... Args&gt;
      void RunVoid(Args... args) {
          JNIEnv *env = this-&gt;GetEnv();
          env-&gt;CallVoidMethod(this-&gt;instanceRef, this-&gt;callbackMethod, args...);
          FreeEnv(env);
      }
  };
  
  struct JNIClass : public SimpleJNIClass {
  
      jclass callbackClass;
      std::unordered_map&lt;std::string, jmethodID&gt; callbacks;
  
  
      JNIClass(JNIEnv *env, jobject classRef)
          : SimpleJNIClass(env, classRef) {
          this-&gt;callbackClass = (jclass)env-&gt;NewGlobalRef((jclass)env-&gt;GetObjectClass(this-&gt;instanceRef));
      };
  
      JNIClass(JNIEnv *env, const std::string &amp; classRefName)
          : SimpleJNIClass(env) {
          this-&gt;callbackClass = (jclass)env-&gt;NewGlobalRef(env-&gt;FindClass(classRefName.c_str()));
      };
  
      virtual ~JNIClass() {
  
          if (JNIEnv * env = GetEnv()) {
              env-&gt;DeleteGlobalRef(callbackClass);
              callbackClass = nullptr;
              FreeEnv(env);
          }
          callbacks.clear();
      };
  
      void AddMethod(const std::string &amp; methodName, const std::string &amp; methodSignature) {
  
          JNIEnv *env = this-&gt;GetEnv();
          this-&gt;callbacks[methodName] = env-&gt;GetMethodID(this-&gt;callbackClass, methodName.c_str(), methodSignature.c_str());
          FreeEnv(env);
      };
  
  
      template&lt;typename... Args&gt;
      void InitNewInstance(Args... args) {
          JNIEnv *env = this-&gt;GetEnv();
          this-&gt;SetInstance(env-&gt;NewObject(this-&gt;callbackClass, this-&gt;callbacks["&lt;init&gt;"], args...));
          FreeEnv(env);
      }
  
      void SetInstance(jobject instRef) {
          JNIEnv *env = this-&gt;GetEnv();
          env-&gt;DeleteGlobalRef(this-&gt;instanceRef);
          this-&gt;instanceRef = env-&gt;NewGlobalRef(instRef);
          FreeEnv(env);
      }
  
      template&lt;typename... Args&gt;
      void RunVoid(const std::string &amp; name, Args... args) {
          JNIEnv *env = this-&gt;GetEnv();
          env-&gt;CallVoidMethod(this-&gt;instanceRef, this-&gt;callbacks[name], args...);
          FreeEnv(env);
      };  
  };
  </code></pre>
  
  <p>in JNI_OnLoad i set global variable <code>JNIClass * fcDataClass</code>:</p>
  
  <pre><code> fcDataClass = new JNIClass(env, "com/example/MyClass");
  </code></pre>
  
  <p>And later in some JNI callback from Android, I have:</p>
  
  <pre><code> int resCount = 3;
   JNIEnv *lockedEnv = fcDataClass-&gt;LockEnv();
   jobjectArray dataArray = lockedEnv-&gt;NewObjectArray(resCount, fcDataClass-&gt;callbackClass, NULL);
  
   //do something with data
   fcDataClass-&gt;UnLockEnv();
  </code></pre>
  
  <p>The problem is, that <code>NewObjectArray</code> crash the whole app with: <code>SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x9c))</code></p>
  
  <p>With callstack:</p>
  
  <pre><code>art::JavaVMExt::JniAbort(char const*, char const*) 0x00000000ef74815c
  art::JavaVMExt::JniAbortV(char const*, char const*, std::__va_list) 0x00000000ef7495ba
  art::ScopedCheck::AbortF(char const*, ...) 0x00000000ef5d8eee
  art::ScopedCheck::CheckThread(_JNIEnv*) 0x00000000ef5d8a0a
  art::ScopedCheck::CheckPossibleHeapValue(art::ScopedObjectAccess&amp;, char, art::JniValueType) 0x00000000ef5d7af2
  art::ScopedCheck::Check(art::ScopedObjectAccess&amp;, bool, char const*, art::JniValueType*) 0x00000000ef5d6fce
  art::CheckJNI::NewObjectArray(_JNIEnv*, int, _jclass*, _jobject*) 0x00000000ef5d3808
  _JNIEnv::NewObjectArray(int, _jclass*, _jobject*) jni.h:858
  </code></pre>