java.lang.InternalError 线程在运行时关闭期间启动

Posted

技术标签:

【中文标题】java.lang.InternalError 线程在运行时关闭期间启动【英文标题】:java.lang.InternalError Thread starting during runtime shutdown 【发布时间】:2016-04-15 17:18:53 【问题描述】:

我们无法获得此异常的确切原因。有谁知道,为什么这个异常发生在android应用程序中?提前致谢。

这是 Exception 的完整堆栈跟踪:

Fatal Exception: java.lang.InternalError: Thread starting during runtime shutdown
       at java.lang.Thread.nativeCreate(Thread.java)
       at java.lang.Thread.start(Thread.java:1063)
       at org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:145)
       at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:125)
       at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.<init>(ThreadSafeClientConnManager.java:103)
       at org.acra.util.HttpRequest.getHttpClient(HttpRequest.java:214)
       at org.acra.util.HttpRequest.send(HttpRequest.java:141)
       at org.acra.sender.HttpSender.send(HttpSender.java:225)
       at org.acra.SendWorker.sendCrashReport(SendWorker.java:179)
       at org.acra.SendWorker.checkAndSendReports(SendWorker.java:141)
       at org.acra.SendWorker.run(SendWorker.java:77)

【问题讨论】:

写完整的调用栈跟踪。 这不是 ANR。应用程序在特定屏幕上崩溃。 github.com/ACRA/acra/issues/196 【参考方案1】:
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) 
  CHECK(java_peer != nullptr);
  Thread* self = static_cast<JNIEnvExt*>(env)->self;

  if (VLOG_IS_ON(threads)) 
    ScopedObjectAccess soa(env);

    ArtField* f = soa.DecodeField(WellKnownClasses::java_lang_Thread_name);
    mirror::String* java_name = reinterpret_cast<mirror::String*>(f->GetObject(
        soa.Decode<mirror::Object*>(java_peer)));
    std::string thread_name;
    if (java_name != nullptr) 
      thread_name = java_name->ToModifiedUtf8();
     else 
      thread_name = "(Unnamed)";
    

    VLOG(threads) << "Creating native thread for " << thread_name;
    self->Dump(LOG(INFO));
  

  Runtime* runtime = Runtime::Current();

  // Atomically start the birth of the thread ensuring the runtime isn't shutting down.
  bool thread_start_during_shutdown = false;
  
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    if (runtime->IsShuttingDownLocked()) 
      thread_start_during_shutdown = true;
     else 
      runtime->StartThreadBirth();
    
  
  if (thread_start_during_shutdown) //At there!!!
    ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/InternalError"));
    env->ThrowNew(error_class.get(), "Thread starting during runtime shutdown");
    return;
  

  Thread* child_thread = new Thread(is_daemon);
  // Use global JNI ref to hold peer live while child thread starts.
  child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
  stack_size = FixStackSize(stack_size);

  // Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
  // assign it.
  env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
                    reinterpret_cast<jlong>(child_thread));

  // Try to allocate a JNIEnvExt for the thread. We do this here as we might be out of memory and
  // do not have a good way to report this on the child's side.
  std::unique_ptr<JNIEnvExt> child_jni_env_ext(
      JNIEnvExt::Create(child_thread, Runtime::Current()->GetJavaVM()));

  int pthread_create_result = 0;
  if (child_jni_env_ext.get() != nullptr) 
    pthread_t new_pthread;
    pthread_attr_t attr;
    child_thread->tlsPtr_.tmp_jni_env = child_jni_env_ext.get();
    CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
    CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED),
                       "PTHREAD_CREATE_DETACHED");
    CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
    pthread_create_result = pthread_create(&new_pthread,
                                           &attr,
                                           Thread::CreateCallback,
                                           child_thread);
    CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");

    if (pthread_create_result == 0) 
      // pthread_create started the new thread. The child is now responsible for managing the
      // JNIEnvExt we created.
      // Note: we can't check for tmp_jni_env == nullptr, as that would require synchronization
      //       between the threads.
      child_jni_env_ext.release();
      return;
    
  

  // Either JNIEnvExt::Create or pthread_create(3) failed, so clean up.
  
    MutexLock mu(self, *Locks::runtime_shutdown_lock_);
    runtime->EndThreadBirth();
  
  // Manually delete the global reference since Thread::Init will not have been run.
  env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer);
  child_thread->tlsPtr_.jpeer = nullptr;
  delete child_thread;
  child_thread = nullptr;
  // TODO: remove from thread group?
  env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
  
    std::string msg(child_jni_env_ext.get() == nullptr ?
        "Could not allocate JNI Env" :
        StringPrintf("pthread_create (%s stack) failed: %s",
                                 PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
    ScopedObjectAccess soa(env);
    soa.Self()->ThrowOutOfMemoryError(msg.c_str());
  

【讨论】:

你不觉得解释会更好

以上是关于java.lang.InternalError 线程在运行时关闭期间启动的主要内容,如果未能解决你的问题,请参考以下文章

是什么导致sun.awt.shell.Win32ShellFolder2.initSpecial()抛出InternalError?

直通线交叉线反转线怎么连接

微带线和带状线有啥异同?

如何使用3线-8线译码器和各种数字集成电路构成一个2线-4线译码器??????请画出电路图!!!!

并口线与串口线的区别在哪?

如何确定山脊线