我对如何正确处理JNI中的关联(或行为)有疑问。

假设在共享库中有两个类,分别是NativeClass1NativeClass2NativeClass1具有方法void fooNative(NativeClass2* nativeObj),该方法允许它对类型为NativeClass2的对象执行某些操作。

对于这些类中的每一个,都定义了一个Java类来包装相应的本机对象(JavaClass1JavaClass2,每个类都有一个long私有成员,该成员指向动态分配的类型为NativeClass1和)。

我希望NativeClass2也具有方法JavaClass1(以及相应的本机方法public void fooJava(JavaClass2 obj),该方法将在强制转换指针后最终调用private native void call_fooNative(long nativeObject1Ptr, long nativeObject2Ptr))。

如何从NativeClass1::void fooNative(NativeClass2* nativeObj)获取基本的长指针(指向NativeClass2的成员)以调用JavaClass2(假设您将void JavaClass1::call_fooNative(long nativeObject1Ptr, long nativeObject2Ptr)的指针作为第一个参数传递)?

我想到了两种方法:


NativeClass1中的长指针创建一个公共的getter方法。


但是每个人都可以访问实际的本机对象,创建另一个共享库,在JavaClass2的void指针上执行delete ptr或以其他方式破坏本机对象。


而不是将指针传递给NativeClass2对象(作为NativeClass2的第二个参数,而是传递类型为call_fooNative(...)的实际java对象,并使用JavaClass2getFieldId确定指针(允许在私有对象上使用)成员,如Java本地接口:程序员指南和规范,作者Liang Liang所言,“ 10.9违反访问控制规则”。


就设计和安全性而言,哪种方法是正确的?

最佳答案

如何从JavaClass2获取基本的长指针(指向NativeClass2),以便调用void JavaClass1 :: call_fooNative(long nativeObject1Ptr,long nativeObject2Ptr)(假设您将指向NativeClass1的指针作为第一个参数传递)?


您的第一种方法可能是合理的。这是SWIG使用的方法。

SWIG是一个开放源代码工具,可为C ++代码生成Java包装器。如果要包装许多类或方法,则可能要考虑使用它。

例如,以下是SWIG生成的一些代码(更改了类名):

public class Foo {
  private long swigCPtr;
  protected boolean swigCMemOwn;

  public Foo(long cPtr, boolean cMemoryOwn) {
    swigCMemOwn = cMemoryOwn;
    swigCPtr = cPtr;
  }

  public static long getCPtr(Foo obj) {
    return (obj == null) ? 0 : obj.swigCPtr;
  }

  ...



  但是每个人都可以访问实际的本机对象,创建另一个共享库,对NativeClass2的void指针执行delete ptr或以其他方式破坏本机对象。


不一定每个人都可以,只有Java和本地代码可以访问对NativeClass2特定实例的引用。


  
  而不是将指针传递给NativeClass2对象(作为call_fooNative(...的第二个参数),而是传递类型为JavaClass2的实际Java对象,并使用getFieldId和getLongField确定指针...
  


这不一定会阻止从Java访问指针。 Java代码可以use reflection to access private fields

08-16 13:14