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

How to add prefixes to jni dll function names

我有一个 jni dll,它具有从 java 调用的函数。问题是这个dll在默认包中(在dll "Java_classname_methodname"中)有所有的java 类。不可能获得此 dll 的源代码,重写将花费非常长的时间。所以我基本上需要从 java 在不同于默认包的包中调用此 dll 中的函数。我已经连续几个小时尝试使用十六进制编辑器和几种工具重命名 dll 中的函数来修改 dll 中的校验和和地址,但这对我来说太多了,因为我几乎没有这方面的经验。我非常喜欢这条路线,但我只是没有合适的工具或专业知识。所以我剩下的就是尝试在 java 中硬编码包名称。我尝试使用 this stack overflow post 中描述的 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 重要)。谢谢你的时间。

I have a JNI dll that has functions being called from java. The problem is that this DLL has all the java classes in the default package (in the dll "Java_classname_methodname").

所以相应的 Java class 与本地方法也不在包中。

It is impossible to get the source of this dll and it would take EXTREMELY long to rewrite. So I basically need to call the functions in this dll from java in a different package than default.

正确。

I've tried for hours on end to rename the functions in the dll with a hex editor and several tools to modify the checksum and addresses in the dll but it's just too much for me because I have almost no experience with this.

您也许能够以某种方式为函数名称起别名,但我在这方面的实践已经有 20 年了。

I would very much prefer this route, but I just don't have the proper tools or the know-how. So what I'm left with is trying to hardcode the package name in java.

没有。没有要硬编码的包名称。您剩下的是尝试在 class 中调用本机方法,而没有来自包中 class 的包,因为 1.4 是不可能的。

您需要做的是:

  1. 可以通过反射调用无包 Java 本机方法。因此,您可以编写一个包装器 class 来执行此操作,它位于您选择的包中,其余代码可以调用包装器。

  1. 如下:

    • 用适当的本机方法在您选择的包中编写另一个 Java class。
    • 从现有的 DLL 创建导入库。
    • 编写另一个 DLL 并 link 使用此导入库。
    • 从您的 Java 代码加载这个新的 DLL。
    • 让此 DLL 在初始化时使用 RegisterNatives 方法,以在新本地方法名称和签名下注册旧 DLL 中现有的 JNI 入口点。
    • 使用 javah 获取所需的本机方法名称,使用 javap 获取所需的 Java 签名。不要试图用手去猜它们。

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