0

我有一个 jni dll,其中包含从 java 调用的函数。问题是这个 dll 包含默认包中的所有 java 类(在 dll“Java_classname_methodname”中)。获取此 dll 的源代码是不可能的,而且重写需要很长时间。所以我基本上需要在与默认不同的包中从 java 调用这个 dll 中的函数。我已经尝试了几个小时使用十六进制编辑器和几个工具来重命名 dll 中的函数来修改 dll 中的校验和和地址,但这对我来说太多了,因为我几乎没有这方面的经验。我非常喜欢这条路线,但我没有合适的工具或专业知识。所以我剩下的就是尝试在java中对包名进行硬编码。我尝试使用 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 重要)。感谢您的时间。

4

1 回答 1

2

我有一个 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。
    • 让这个 DLLRegisterNatives在初始化时使用该方法,在新的本机方法名称和签名下注册旧 DLL 中的现有 JNI 入口点。
    • 用于javah获取所需的本机方法名称并javap获取所需的 Java 签名。不要试图用手猜测它们。

不要问我这是如何映射到 .so 文件的。

于 2016-08-10T05:17:38.287 回答