2014-11-21 47 views
1

我們有一個應用程序,其中大部分代碼都是用C++編寫的。我們正在使用JNI接口。使用這個JNI接口將事件回調傳遞給java。對於每個事件回撥,我們得到JNIEnv,然後撥打該env的AttachCurrentThread。以下是該行這一段代碼:當調用attachCurrentThread時ART下的本地崩潰

CJniEnvUtil::CJniEnvUtil(JavaVM *pvm) 
: m_fNeedDetach(false) 
, mJavaVM(pvm) 
, m_pEnv(NULL) 
{ 
    switch (mJavaVM->GetEnv((void**)&m_pEnv, JNI_VERSION_1_6)) { 
     case JNI_OK: break; 
     case JNI_EDETACHED: 
      if (mJavaVM->AttachCurrentThread(&m_pEnv, NULL) != 0) { 
       break; 
      } 
      m_fNeedDetach = true; 
      break; 
     case JNI_EVERSION: 
      break; 
    } 
} 

CJniEnvUtil::~CJniEnvUtil() 
{ 
    if (m_fNeedDetach && m_pEnv) 
     mJavaVM->DetachCurrentThread(); 
} 

這樣的想法是,對於每一個事件回調,我們創建這個CJniEnvUtil這反過來又得到ENV當前線程,重視當前線程的實例。當這個CJniUtil對象是析構函數時,這個線程被分離。在Dalvia上,這段代碼工作得非常好,但在ART(Android Run Time)上它正在崩潰(Inface的理智失敗)。 以下是來自logcat的完整堆棧跟蹤。

A/art﹕ art/runtime/thread.cc:468] Check failed: &stack_variable > reinterpret_cast<void*>   (stack_end_) (&stack_variable=0x4cd061b0, reinterpret_cast<void*>(stack_end_)=0x50014000) 
I/AudioFlinger﹕ BUFFER TIMEOUT: remove(4098) from active list on thread 0xb5e81008 
A/art﹕ art/runtime/runtime.cc:203] Runtime aborting... 
A/art﹕ art/runtime/runtime.cc:203] Aborting thread: 
A/art﹕ art/runtime/runtime.cc:203] "<native thread without managed peer>" prio=5 tid=27 Runnable (still starting up) 
A/art﹕ art/runtime/runtime.cc:203] | group="" sCount=0 dsCount=0 obj=0x00000000 self=0x497e4830 
A/art﹕ art/runtime/runtime.cc:203] | sysTid=10564 nice=0 cgrp=apps sched=0/0 handle=0x4f2e9cd0 
A/art﹕ art/runtime/runtime.cc:203] | state=R schedstat=(3985475838 2078977182 16206) utm=335 stm=63 core=0 HZ=100 
A/art﹕ art/runtime/runtime.cc:203] | stack=0x50010000-0x50014000 stackSize=1016KB 
A/art﹕ art/runtime/runtime.cc:203] native: art::Thread::DumpStack(std::ostream&) const+87   
A/art﹕ art/runtime/runtime.cc:203] native: art::Runtime::Abort()+79 [0x41634974] (libart.so) 
A/art﹕ art/runtime/runtime.cc:203] native: art::LogMessage::~LogMessage()+505 [0x414e193a] (libart.so) 
A/art﹕ art/runtime/runtime.cc:203] native: art::Thread::InitStackHwm()+849 [0x4163da9a] (libart.so) 
A/art﹕ art/runtime/runtime.cc:203] native: art::Thread::Init(art::ThreadList*,  art::JavaVMExt*)+499 [0x4163dd78] (libart.so) 
A/art﹕ art/runtime/runtime.cc:203] native: art::Thread::Attach(char const*, bool, _jobject*, bool)+103 [0x41645250] (libart.so) 
A/art﹕ art/runtime/runtime.cc:203] native: art::Runtime::AttachCurrentThread(char const*, bool, _jobject*, bool)+15 [0x41632b38] (libart.so) 

正如第一行所示,理智檢查失敗。

我真的很感激,如果有人可以提出這方面的建議。我必須讓應用程序在Android 5.0上運行,它具有ART作爲默認運行時。

+0

見_ [請問我的Android應用程序還是藝術,而不是運行Dalvik的?](https://software.intel.com/en-us/blogs/2014/ 07/23/will-my-android-app-still-run-with-art-instead-of-dalvik)_:** 11 **觀察pthread大小(pthreat_attr_setstack()和pthreat_attr_setstacksize()),包括AttachCurrentThread )會拋出一個錯誤。 – 2014-11-21 10:33:08

回答

0

Dalvik爲原生代碼和Java代碼提供了單獨的堆棧,默認的Java堆棧大小爲32KB,默認的本地堆棧大小爲1MB。 ART具有統一的堆棧以實現更好的局部性。通常,ART線程的堆棧大小應該與Dalvik大致相同。但是,如果您明確設置堆棧大小,則可能需要重新訪問ART中運行的應用程序的這些值。

在Java中,檢查對Thread構造函數的調用,它指定一個顯式的堆棧大小。例如,如果發生StackOverflowError,則需要增加大小。 在C/C++中,查看也通過JNI運行Java代碼的線程使用pthread_attr_setstack()和pthread_attr_setstacksize()。下面是一個應用程序嘗試在pthread尺寸太小時調用JNI AttachCurrentThread()時記錄的錯誤示例: F/art:art/runtime/thread.cc:435] 嘗試附加一個線程 - 小型堆(16384個字節)

https://developer.android.com/guide/practices/verifying-apps-art.html#Stack_Size