I'm writing a C++ dll (file extension in Visual Studio is .cpp but the code is C) which uses JNI for loading and calling instance methods of some Java classes. As a result my project is made up by C++ source and header files plus some Java class files (the class files for the Java objects used through JNI). I would like to create a single dll library including also the Java class files "in a single bundle". Is it possible to put both the C and Java files into the dll?
This is perfectly possible, though not necessarily intuitive. I haven't tested this but I would imagine it would work easily if you knew what you were doing.
First off, you're going to need a way to package the class file's binary into the native binary you own, and then of course be able to seamlessly read that chunk at any point in time. How you achieve this is up to you, there is no real 'right way' to do it.
That being said, if you can get a handle to the memory where the .class file's data resides (after loading the DLL) and pass it to Java as a byte[] or ByteBuffer, you'd then want to use any one of ClassLoader's defineClass overloads along with a call to findLoadedClass and then finally loadClass.
This would allow you to load in a class from virtually any data source. As I mentioned before, how you store/retrieve the native data for the class is up to you.
Related
I've been trying to find an answer to this for some time, but I think part of my problem is that I don't really know how to phrase my question. I understand the that JVM ultimately preforms all the system calls at run-time that the Java program needs to make, my confusion is about the underlying way that Java classes tell the JVM to do this.
Take for example, the File class in the standard Java library. As far as I know, this is considered the most fundamental API for opening/creating files in Java. But, File is just another class right? So in theory I should be able to write my own File class from scratch which doesn't utilize the pre-exisitng one, right? How would I do that? What is happening inside the File class that tells the VM to actually create the file? I looked at the source code for the File class, and it looks like it calls another class called VMFile, but I could find no explanation of what VMFile is. When I looked at the VMFile source code, it just had function declarations with no definitions.
Thank you for your help.
The Java Native Interface (JNI) is the glue between Java classes and the OS. Native methods have a 'native' attribute (look it up in the JLS).
Libraries such as ASM, BCEL, Javaassist and AspectJ are all capable of runtime bytecode manipulation but how do they achieve this?
I have done some basic bytecode manipulation using ASM before but i don't understand how it works. Is the Java Agent executed in the JVM before the remainder of the program, allowing for ASM to load the compiled classes and edit them before they are executed by the JVM?
If so, is it possible to perform java bytecode manipulation without using an external library like ASM and loading the compiled class files with an BufferedReader and writing a custom parser etc. for example?
These libraries settle on standard Java APIs which, of course, you can also use yourself without these libraries.
First of all, Java class files are just sequences of bytes in a well defined format, as specified in JVMS §4, The class File Format. The primary task of the mentioned libraries is to provide tools for processing byte sequences in this format. The second is about getting the definitions of existing or exporting modified or newly created classes.
There are two different way of dealing with the second task. One is to read compiled classes from persistent storage like file systems or jar files, etc. and writing them back to these storage while the particular code is not running, like build and deployment tools do. This should be trivial, as it just boils down to reading and writing bytes.
The other is to manipulate classes at runtime, which can be done by Java Agents via the Instrumentation API. It offers mechanisms for intercepting classes at loading/definition time before their first use, but also redefinition of classes. The latter can’t change them freely, currently, it has to retain all field and method declarations, so it can be mainly used to change the executable code of the methods.
If you want examples for class file processing without additional 3rd party libraries, there are some answers on Stackoverflow
Extract the class name from a class file
Find all class dependencies
Parse the constant pool
Iterate over all instructions of a method
Of course, these examples are only single-purpose code or sketches. If you expand them to something more general or useful, you will soon end up at basically re-implementing these libraries.
Class files are just a sequence of bytes, the format of which is specified in The Java Virtual Machine Specification. BufferedReader is for text files so you'd want BufferedInputStream, but the format is quite complicated.
You can load manipulated class files as if they were generated by javac. You can also load them dynamically with java.net.URLClassLoader.newInstance or similar. Java Agent allows modification of class files as they are loaded, either through a Java or a native interface (the latter being necessary if you want to modify classes the are loaded before classes that load classes).
Recently java development group at Oracle announced a new JEP( Java enhancement proposal) for class file manipulation. Now we will not need any additional libraries.
https://openjdk.org/jeps/8280389
I'm trying to read a .qm translation files with Java.
.qm files are binary files. I don't have access to the .ts files.
And I don't find much info on these .qm files.
How are they structured ?
Regards,
There's no documentation that I know of, but if you look at QTranslator::load you should be able to follow the format of the QM file.
You will probably need to reimplement QTranslator in Java, as you need not only the ability to load the files, but also to extract and apply translations in Qt fashion.
As per request of OP:
You could use those files by using the Qt libraries and JNI. By using the translator in a c++ dll you can translate strings easily. However, you cannot extract the files or list the contained translations. But if all you need is the actual translation, this solution should work.
I cannot give a real example, because I only now how it works in theory, I haven't tried it, because it's not trivial. But if you are eager to try it out, the general idea would be:
Create a C++ dll and build it against QtCore. The easiest way is to download Qt from their website qt.io. You can for example create a default library project with QtCreator. Note: Besides Qt5Core.dll, Qt requires other libraries to correctly run. They are all included in the installation, but once you deploy your application, those of course have to be includes as well.
Include JNI to the C++ project and link against it. if you're new to this, here is a nice tutorial: Java Programming Tutorial
Create your wrapper methods. Methods in cpp you can call from java that take java strings, convert them to QString, translate them with QTranslator and convert them back.
Load the library in Java and execute those methods
Important:
First, I don't know how java handles dll dependencies. If you encounter errors while loading the dll, it's probably because dependencies of your dll are not present. Second, Qt typically requires a QCoreApplication running in the main thread for most of it's operations. I tested the translator without such an app, and it worked. So apparently for translations only the app is not required. However, depending on what you do in your dll, I think this is important to know.
If you need more details, feel free to ask.
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.
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:
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
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.
I have an applet which contains some images, regular java classes and class, which uses C code via JNI. All this is included in jar file, and the appropriate dll is located somewhere on a harddrive. In C code I have to read a bitmap from the applet(jar). I know that it is simple to access this file from java via getResourceAsStream() method, but can I do it from native code?
I understand that I can pass the bytes of the bitmap to native code as a workaround, but it requires some rewriting, so I would like to avoid this.
So, is there any way to access files from within jar via native code, executed by class belonging to this jar?
Just call the appropriate Java methods.