0

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"). 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. 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. I tried using jna as described in this stack overflow post to do something like this:

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);

But there is no setName in Method. Ideally I'd like to get this done without any extra libraries but I'm obviously not opposed to using something like jna. And before anyone asks, yes this is permitted by the library's usage license. Please don't tell me it's not possible because know that it's possible, just difficult. Whichever way it must be done I am willing to put in the work (either modifying dll or using java code with some external library). And by the way, I also need this done on .so and .dylib files eventually (not as important as dll). Thank you for your time.

Community
  • 1
  • 1
user3441843
  • 137
  • 1
  • 7
  • Do you mean the dll contains java classes? with a package structure? If so can i know why you are doing this, i mean java classes in a dll – Sanjit Kumar Mishra Aug 10 '16 at 04:51
  • @SanjitKumarMishra No, he does not mean that. He has JNI functions in a DLL *without* package structure, that were called (a long time ago) from a Java class, not in a package, with native methods. Since 1.4 he cannot now call that class from a class in a package. – user207421 Aug 10 '16 at 05:07

1 Answers1

2

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").

So the corresponding Java class with the native methods wasn't in a package either.

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.

Correct.

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.

You may be able to alias the function names somehow, but it's been about 20 years since I practiced in this area.

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.

No. There is no package name to hard-code. What you're left with is trying to call native methods in a class without a package from a class in a package, which since 1.4 is not possible.

What you need to to do is either:

  1. It is possible to call the package-less Java native methods via reflection. So, you can write a wrapper class that does that, which lives in the package of your choice, and the rest of your code can call the wrapper.

Or

  1. As follows:

    • Write another Java class in the package of your choice with the appropriate native methods.
    • Create an import library from the existing DLL.
    • Write another DLL and link it with this import library.
    • Load this new DLL from your Java code.
    • Have this DLL use the RegisterNatives method on initialization, to register the existing JNI entry points in the old DLL under the new native method names & signatures.
    • Use javah to get the required native method names and javap to get the required Java signatures. Don't try to guess them by hand.

Don't ask me how this maps to .so files.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Would it be possible to create a separate jar file compiled to JDK 1.3 specs that contains a package with a wrapper class around the problematic outside-of-a-package class? Then use that class from within that jar file from, say, a JDK 8 application? – Andrew Henle Aug 10 '16 at 12:04
  • @AndrewHenle Tried that. You can't import the package-less class, even with -source 1.3. You would need a 1.3 compiler. The reflective solution does work. – user207421 Aug 11 '16 at 06:26
  • The problem with reflection is that id really like to repackage and refactor these classes and it wont be possible without creating a wrapper class which consists of hundreds of invoke calls to Methods and creating a jar of the original default package to hide them. I opted for the custom dll option which calls functions in the original one. I successfully created the dll, but I soon realized that there are also JNI>Java calls which will not work with repackaged classes. Am I screwed on this front? – user3441843 Aug 11 '16 at 08:50
  • Again you will have to provide a wrapper, in this case an inverse wrapper, that satisfies what the legacy JNI is expecting and calls your own callback classes defined in packages. It isn't clear how you can possibly know what those are without access to the source code. – user207421 Aug 11 '16 at 10:04
  • Wouldn't that just be the same as rewriting the original dll?I'm not quite understanding how the original dll code would be called – user3441843 Aug 11 '16 at 10:53