getDeclaredMethods / getDeclaredFields / getConstructors的替代方案

时间:2013-10-13 00:57:44

标签: java delphi java-native-interface

由于在上述方法中调用了Reflection.getCallerClass,我在调用getDeclaredMethods / getDeclaredFields / getConstructors时获得了AV。

我已经从Delphi应用程序通过JNI创建了一个Java VM。不幸的是,我发现在调用java.lang.Class类中的某些方法时,这些方法调用

checkMemberAccess(1, Reflection.getCallerClass(), true);

导致AV,因为堆栈上没有真正的Java类,因为我直接调用了getDeclaredXXX方法,并且来自Delphi的JNI调用。

为了克服getCallerClass,我创建了一个Java类包装器,如下所示:

public class DelphiClassHelper {

  private Field[] f;
  private Method[] m;
  private Constructor<?>[] c;
  private static DelphiClassHelper helper;

  public Field[] pGetDeclaredFields(ClassLoader cl, String ClassName) {
    Class<?> AClass = null;
    try {
        System.out.println("Loading class: "+ClassName);
        System.out.println("ClassLoader: "+cl.toString());
        AClass = cl.loadClass(ClassName);
    } catch (ClassNotFoundException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }  
    if (AClass!=null) {
        f = AClass.getDeclaredFields();
        return f;
    } else
        return new Field[]{};
  }

  public static Field[] GetDeclaredFields(ClassLoader cl, String ClassName) {
     helper = new DelphiClassHelper();
     return helper.pGetDeclaredFields(cl, ClassName);
  }

  public Method[] pGetDeclaredMethods(ClassLoader cl, String ClassName) {
    Class<?> AClass = null;
    try {
        System.out.println("Loading class: "+ClassName);
        System.out.println("ClassLoader: "+cl.toString());
        AClass = cl.loadClass(ClassName);
    } catch (ClassNotFoundException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }  
    if (AClass!=null) {
        m = AClass.getDeclaredMethods();
        return m;
    } else
        return new Method[]{};
  }

  public static Method[] GetDeclaredMethods(ClassLoader cl, String ClassName) {
     helper = new DelphiClassHelper();
     return helper.pGetDeclaredMethods(cl, ClassName);
  }

  public Constructor<?>[] pGetConstructors(ClassLoader cl, String ClassName) {
    Class<?> AClass = null;
    try {
        System.out.println("Loading class: "+ClassName);
        System.out.println("ClassLoader: "+cl.toString());
        AClass = cl.loadClass(ClassName);
    } catch (ClassNotFoundException e) {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }  
    if (AClass!=null) {
        c = AClass.getConstructors();
        return c;
    } else
        return new Constructor[]{};
  }

  public static Constructor<?>[] GetConstructors(ClassLoader cl, String ClassName) {
     helper = new DelphiClassHelper();
     return helper.pGetConstructors(cl, ClassName);
  }

}

我创建上面的想法是公共静态方法创建一个Java类,然后调用实例方法pXXXX,然后调用其中一个方法Class.getDeclaredMethods,getDeclaredFields,getConstructors,这肯定会满足getCallerClass调用因此,防止AV。

但不,我仍然得到AV。是否有任何其他框架可以提供getDeclaredXXXX方法提供的信息,或者是否有办法解决getCallerClass要求,例如在堆栈上创建一个可以满足Reflection.getCallerClass调用的假类?

我的Delphi到JNI应用程序的其他部分工作,只要它不调用最终调用Reflection.getCallerClass的任何Java方法。

注意,当我从JNI调用创建Java VM时,没有安装任何SecurityManager。

更新:2014年1月24日 AV的原因是由于一些优化,这导致对象的实例被放置在一个CPU寄存器中,在调用checkMemberAccess时会被擦除。随后当Delphi运行时尝试从CPU寄存器中检索对象并再次使用它时,它会导致AV,因为预期值已被删除。

1 个答案:

答案 0 :(得分:0)

您的方法似乎正确无误。问题是你在方法中关于ClassLoader c1参数传递了什么?这需要使用与您尝试内省的类相同的VM中的类生成。任何课程都可以。如果你有这样的类,你可以在它的构造函数中使用该类获得正确的ClassLoader。