2011-09-28 68 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:为了确保它是相同的字节码,除了检查字节码以外别无他法。但我敢打赌,它是。 –