如何为jni dll函数名添加前缀

时间:2016-08-10 04:37:56

标签: java dll java-native-interface package default-package

我有一个jni dll,它具有从java调用的函数。问题是这个dll包含默认包中的所有java类(在dll" Java_classname_methodname"中)。获取此dll的源代码是不可能的,并且重写需要很长时间。所以我基本上需要在java中调用这个dll中的函数,而不是默认的。我已经尝试了几个小时,用十六进制编辑器和几个工具重命名dll中的函数来修改dll中的校验和和地址,但这对我来说太过分了,因为我几乎没有经验有了这个。我非常喜欢这条路线,但我没有适当的工具或技术诀窍。所以我剩下的就是尝试在java中对软件包名称进行硬编码。我尝试使用this堆栈溢出帖子中描述的jna来做这样的事情:

Map options = new HashMap();

options.
    put(
        Library.OPTION_FUNCTION_MAPPER, 
        new StdCallFunctionMapper() {
            public String getFunctionName(NativeLibrary library, Method method) {
                method.setName(method.getName().replace("com.test.", "");
                return super.getFunctionName(library, method);
            }
        }
    );

Native.loadLibrary(..., ..., options);

但是在Method中没有setName。理想情况下,我希望在没有任何额外库的情况下完成此操作,但我显然不反对使用像jna这样的东西。在任何人问之前,是的,这是图书馆的使用许可证所允许的。请不要告诉我这是不可能的,因为知道它是可能的,只是困难。无论采取哪种方式,我都愿意投入工作(修改dll或使用带有一些外部库的java代码)。顺便说一句,我还需要在.so和.dylib文件上完成这个(不像dll那么重要)。谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

  

我有一个JNI dll,它具有从java调用的函数。问题是这个DLL拥有默认包中的所有java类(在dll“Java_classname_methodname”中)。

因此,具有本机方法的相应Java类也不在包中。

  

获取此dll的源代码是不可能的,并且重写需要很长时间。所以我基本上需要在java中调用这个dll中的函数,而不是默认的。

正确。

  

我已经尝试了几个小时来重命名dll中的函数,使用十六进制编辑器和几个工具来修改dll中的校验和和地址,但这对我来说太过分了,因为我几乎没有经验。

你可能会以某种方式为功能名称添加别名,但是我在这个领域练习已经有20年了。

  

我非常喜欢这条路线,但我没有适当的工具或技术诀窍。所以我剩下的就是尝试在java中对软件包名称进行硬编码。

没有。硬编码没有包名。你剩下的就是尝试在类中调用本机方法,而不需要包中的类包,因为1.4是不可能的。

您需要做的是:

  1. 可以通过反射调用无包的Java本机方法。因此,您可以编写一个包装类来实现它,它位于您选择的包中,其余代码可以调用包装器。
    1. 如下:

      • 使用适当的本机方法在您选择的包中编写另一个Java类。
      • 从现有DLL创建导入库。
      • 编写另一个DLL并将其与此导入库链接。
      • 从Java代码加载此新DLL。
      • 让这个DLL在初始化时使用RegisterNatives方法,在新的本机方法名称下注册旧DLL中的现有JNI入口点。签名。
      • 使用javah获取所需的本机方法名称,使用javap获取所需的Java签名。不要试图手工猜测它们。
    2. 不要问我这是如何映射到.so文件的。