从本地代码访问Java同步方法

9

我有一个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属性已经强制执行了方法同步。我不太关心重写代码,我可以想到几个解决方法来解决这个问题,但我对于从本地代码调用的同步方法的行为很感兴趣。

3个回答

6

Java语言规范的第8.4.3.6节“同步方法”指出,声明同步方法与在方法内添加同步块具有相同的效果。


谢谢!鉴于它们被指定具有相同的效果,我将假设它们生成相同的字节码,因此在这里不需要/冗余MonitorEnter/MonitorExit。 - Eric Moors

3
不需要显式的MonitorEnter/MonitorExit。根据JNI指南,最好使用Java编程语言表达同步构造。例如,如果静态本地方法需要进入与其定义类相关联的监视器,则应定义静态同步本地方法,而不是在本地代码中执行JNI级别的监视器同步。即使您从本地代码调用Java方法(而不是反之),该规范也没有直接讨论您的情况,但也没有说明相反,因此我会假设它的工作方式类似。

谢谢。我之前找到过这些信息,但由于这是相反的方向,我不太确定。如果同步方法编译成类似于method() { synchronized(this) { method body} }的东西,我也不会有问题。我只是不确定为此生成了什么字节码,以及jni调用的入口点究竟是什么。 - Eric Moors
@Eric Moors:要绝对确定它是相同的字节码,除了检查字节码之外没有其他方法。但我几乎可以打赌它是相同的。 - Joonas Pulakka

0
如果您拥有SomeClass,您只需执行以下操作:
public class SomeClass {
private static synchronized void method() {
     //do something that needs synchronization
   }

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

只需从 C++ 调用 synchronizedMethod() 即可。


当然,那是其中一种选择。不过正如我所说,我并不是很感兴趣重新编写代码。我想要了解正在发生的事情。 - Eric Moors

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接