The interaction of Java and ... Assembler?
In Java, it is possible to use program code implemented in other programming languages, the so-called JNI . You can write a dynamically linked library, then load it in Java code and use the functions from there, declaring them as the native methods of the class that loaded it. JNI was created primarily in order to perform machine-dependent actions (and also, possibly, improve the performance of speed-critical parts of the application) in C / C ++, but no one bothers us from writing a library in assembler too.
To create this distortion, we used Windows, Oracle JDK, Yasm (without macros) and the linker from Microsoft Visual Studio 2010. If you wanted, it would not be difficult to replace any of these components with your favorite, I tried not to use any non-standard features.
To begin, let's create a class in Java in which a function from a future .dll will be called:
Now we need to find out what function name the Java machine expects to find in our library. We will use the javah program from the JDK for this: In this case, a C ++ header will be generated:
The information contained here is needed mainly for further writing the library in C ++, but we are only interested in the signature of the function:
We see that in the dll the function should have the name JNICALL Java_TestJNI_sum and take 4 parameters. For the simplest functions, we will not need the first two of them. All sorts of strange data types like JNIEXPORT, as you might guess, are declared in the jni.h file, which is part of the JDK.
Let's write the library:
Compile and link: At the output, we get a .dll file, which we need to transfer to Java code.
We put the files mydll.dll and TestJNI.class in one folder and see what happened: This is a victory, we learned how to add two numbers! If suddenly someone became interested, then the following links will come in handy:
Tools
To create this distortion, we used Windows, Oracle JDK, Yasm (without macros) and the linker from Microsoft Visual Studio 2010. If you wanted, it would not be difficult to replace any of these components with your favorite, I tried not to use any non-standard features.
Using JNI
To begin, let's create a class in Java in which a function from a future .dll will be called:
public class TestJNI {
native static int sum(int x, int y); // импортируемая функция sum
public static void main(String[] args) {
System.loadLibrary("mydll"); // загружаем библиотеку mydll.dll
System.out.println(sum(2, 3)); // вызываем функцию
}
}
Name Mangling in Java
Now we need to find out what function name the Java machine expects to find in our library. We will use the javah program from the JDK for this: In this case, a C ++ header will be generated:
javac TestJNI.java
javah TestJNI
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class TestJNI */
#ifndef _Included_TestJNI
#define _Included_TestJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: TestJNI
* Method: sum
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_TestJNI_sum
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
The information contained here is needed mainly for further writing the library in C ++, but we are only interested in the signature of the function:
JNIEXPORT jint JNICALL Java_TestJNI_sum
(JNIEnv *, jclass, jint, jint);
We see that in the dll the function should have the name JNICALL Java_TestJNI_sum and take 4 parameters. For the simplest functions, we will not need the first two of them. All sorts of strange data types like JNIEXPORT, as you might guess, are declared in the jni.h file, which is part of the JDK.
Assembler
Let's write the library:
;mydll.asm
section .text
global Java_TestJNI_sum
Java_TestJNI_sum:
mov eax, [esp + 12] ; игнорируем первые 2 параметра
add eax, [esp + 16]
ret 16
end
;mydll.def
LIBRARY mydll
EXPORTS Java_TestJNI_sum
Compile and link: At the output, we get a .dll file, which we need to transfer to Java code.
yasm -f win32 mydll.asm
link /SUBSYSTEM:windows /DLL /NOENTRY /DEF:mydll.def mydll.obj
Result
We put the files mydll.dll and TestJNI.class in one folder and see what happened: This is a victory, we learned how to add two numbers! If suddenly someone became interested, then the following links will come in handy:
>java TestJNI
5
- Invoking Assembly Language Programs from Java is a very good and much more detailed article in English on this subject;
- Writing dll in assembler for external calling in Maple - creating an assembler library for Maple;
- Java Native Interface: Programmer's Guide and Specification - a thick book on JNI.