2013-09-30 65 views
5

我們有一個Java服務器(Linux 64位)應用程序,它使用本機代碼處理其內容。本地代碼也可處理所有多線程問題,並且最近使用boost::context進行了光纖切換。上下文切換本地線程無法連接到JVM

我們現在面臨的問題是AttachCurrentThread光纖交換線程失敗。經過一些長時間的調試和測試後,我們發現原因如下:JVM似乎拒絕具有不同於創建時所指定的堆棧指針的線程。

我們通過簡單地將pthread從修改過的rsp修改爲rsp而失敗,從而驗證了這一點。

一個可能的修復會引入某種事件處理機制來解耦來自光纖交換線程的回調,但我真的想避免這種情況。

有沒有人知道這個解決方法?

是否可以禁用堆棧檢查(Oracle Java 1.7.0_40,64位)?

我們可以修改本地pthreads指向正確的堆棧幀(我懷疑我們可以)嗎? (我們不能提前設置堆棧幀)。

+1

我知道它並沒有完全回答你的問題,但是你可以嘗試用Java世界中的一些光纖實現替換你的boost :: context光纖(用C++實現)。在這種情況下,它們通常被稱爲協同程序。 這裏有一些現有的實現:[可用的Java中的協同庫](http://stackoverflow.com/questions/2846428/available-coroutine-libraries-in-java) –

+0

你有沒有找到這個解決方案?我試圖利用Boost.Coroutine,並且需要在這樣的例程中從JNI回調Java空間,這會導致很多失敗... – NuSkooler

回答

0

免責聲明:這不是一個真正的答案,因爲我沒有直接解決RSP交換機問題,但是發表評論太長了。

根據我的經驗,您應該只附加一次本地線程,並在退出前準確分離一次。如果你不知道你是否已經連接,使用此代碼:

jint rv = vm->GetEnv((void**)&env, JNI_VERSION_1_6); 
if (rv == JNI_EDETACHED) { 
    vm->AttachCurrentThread((void**)&env, 0); 
} 

我建議第一,確保您連接到線恰好一次創建任何關聯的纖維之前,以及恰好一次分離每個本地線程退出之前(或根本沒有,如果本地線程不終止)。