2011-09-28 49 views
9

我有一個java類,有一些(私有靜態)同步方法,我也想從本地代碼調用。一些示例代碼,它變得更加清楚明白我的意思從本機代碼訪問java同步方法

public class SomeClass { 
    private static synchronized void method() { 
    //do something that needs synchronization 
    } 
} 

和相關的本地代碼(C++)

void someFunction(JNIEnv * env) { 
    jclass someClass = env->findClass("SomeClass"); 
    jmethodID methodId = env->GetStaticMethodID(jclass, "method", "()V"); 
    env->MonitorEnter(jclass); // <--- IS THIS NEEDED/ALLOWED 
    env->CallStaticVoidMethod(jclass, methodId); 
    env->MonitorExit(jclass); // <--- IS THIS NEEDED/ALLOWED 
} 

因此,我想知道是,如果我需要調用MonitorEnter/MonitorExit,或者如果方法同步已經通過SomeClass.method()的synchronized屬性強制執行。 我對重寫代碼沒有那麼感興趣。我可以考慮一些解決方法來解決這個問題,但是我對這個行爲是什麼感興趣,給定一個從本地代碼調用的同步方法。

回答

6

Java語言規範的8.4.3.6 synchronized Methods部分說,聲明方法同步與在方法中添加同步塊具有相同的效果。

+0

謝謝!鑑於這些被指定具有相同的效果,我會假設它們生成相同的字節碼,所以MonitorEnter/MonitorExit在這裏不需要/多餘。 –

0

如果你擁有SomeClass你可以做

public class SomeClass { 
private static synchronized void method() { 
    //do something that needs synchronization 
    } 

private static void synchronizedMethod() { 
    method(); 
    } 
} 

並調用synchronizedMethod()從C++。

+0

當然,這是其中一種選擇。就像我說的那樣,我對重寫代碼不感興趣。我想了解發生了什麼。 –

3

不,不需要顯式MonitorEnter/MonitorExit。根據The JNI guide,

......最好用Java編程語言表達同步結構。例如,如果靜態本機方法需要輸入與其定義類關聯的監視器,則應該定義一個靜態同步本機方法,而不是在本機代碼中執行JNI級監視器同步。

即使您從本機代碼調用Java方法(而不是相反)不規範,直接討論的情況下,相對沒有說明要麼,所以我會假設它的工作原理與此類似。

+0

謝謝。我之前找到過這方面的信息,但由於這是相反的方向,所以我不太確定。如果同步方法被編譯成與方法(){synchronized(this){method body}}類似的東西,那麼我也沒有問題。我只是不確定爲此生成了什麼字節碼,以及jni調用的入口點究竟是什麼。 –

+0

@Eric Moors:爲了確保它是相同的字節碼,除了檢查字節碼以外別無他法。但我敢打賭,它是。 –