【问题标题】:access java synchronized method from native code从本机代码访问 java 同步方法
【发布时间】:2011-09-28 12:53:20
【问题描述】:

我有一个 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() 上的同步属性强制执行。 我对重写代码不太感兴趣。我可以想出一些解决方案来解决这个问题,但我对行为是什么感兴趣,给定一个从本机代码调用的同步方法。

【问题讨论】:

    标签: java java-native-interface synchronized


    【解决方案1】:

    Java 语言规范的8.4.3.6 synchronized Methods 部分指出,声明方法同步与在方法中添加同步块具有相同的效果。

    【讨论】:

    • 谢谢!鉴于这些被指定为具有相同的效果,我将假设它们确实生成相同的字节码,因此此处不需要/冗余 MonitorEnter/MonitorExit。
    【解决方案2】:

    不,不需要明确的MonitorEnter / MonitorExit。根据The JNI guide

    ...最好用 Java 编程语言表达同步结构。例如,如果静态本地方法需要进入与其定义类关联的监视器,则应定义静态同步本地方法,而不是在本地代码中执行 JNI 级别的监视器同步。

    尽管规范中没有直接讨论您从本机代码调用 Java 方法的情况(反之亦然),但也没有说明相反的情况,所以我会假设它的工作原理类似。

    【讨论】:

    • 谢谢。我以前发现过这个信息,但由于这是相反的方向,我不太确定。如果同步方法被编译成类似于 method() { synchronized(this) { method body} } 的东西,我也希望没有问题。我只是不确定为此生成了什么字节码,以及 jni 调用的入口点到底是什么。
    • @Eric Moors:要绝对确定它是相同的字节码,除了检查字节码之外别无他法。但我几乎敢打赌。
    【解决方案3】:

    如果你拥有SomeClass,你可以这样做

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

    只需从 C++ 调用 synchronizedMethod()

    【讨论】:

    • 当然,这是备选方案之一。就像我说的,我对重写代码没那么感兴趣。我想了解发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多