Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code injecting/assembly inlining in Java?

I know Java is a secure language but when matrix calculations are needed, can I try something faster?

I am learning __asm{} in C++, Digital-Mars compiler and FASM. I want to do the same in Java. How can I inline assembly codes in functions? Is this even possible?

Something like this (a vectorized loop to clamp all elements of an array to a value without branching, using AVX support of CPU):

JavaAsmBlock(
   # get pointers into registers somehow
   # and tell Java which registers the asm clobbers somehow
     vbroadcastss  twenty_five(%rip), %ymm0
     xor   %edx,%edx
.Lloop:                            # do {
    vmovups   (%rsi, %rdx, 4), %ymm1
    vcmpltps   %ymm1, %ymm0, %ymm2
    vblendvps  %ymm2, %ymm0, %ymm1, %ymm1  # TODO: use vminps instead
    vmovups    %ymm1, (%rdi, %rdx, 4)
    # TODO: unroll the loop a bit, and maybe handle unaligned output specially if that's common
    add         $32, %rdx
    cmp         %rcx, %rdx
    jb     .Lloop                  # } while(idx < count)
    vzeroupper
);

System.out.println(var[0]);

I don't want to use a code-injector. I want to see the Intel or AT&T style x86 instructions.

like image 993
huseyin tugrul buyukisik Avatar asked Jul 24 '12 13:07

huseyin tugrul buyukisik


People also ask

What is assembly in Java?

Assembly Language is the interface between higher level languages (C++, Java, etc) and machine code (binary). For a compiled language, the compiler transforms higher level code into assembly language code.

What is inline assembly explain with an example?

In computer programming, an inline assembler is a feature of some compilers that allows low-level code written in assembly language to be embedded within a program, among code that otherwise has been compiled from a higher-level language such as C or Ada.

Is inline assembly faster?

It's even possible on most compilers to include a little bit of assembly code right inside your C or C++ file, called "inline assembly" because the assembly is inside the C/C++. This is usually a bit faster (because no function call overhead) and simpler (less hassle at build time) than having a separate ".

What is inline instruction?

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory. This eliminates call-linkage overhead and can expose significant optimization opportunities.


2 Answers

There is a layer of abstraction between your Java code and the underlying hardware that makes this kind of thing impossible in principle; you technically can't know how your code is represented on the underlying machine, since the same bytecode can run on different processors and different architectures.

What you officially can do is use the Java Native Interface (JNI) to call native code from your Java code. The call overhead is substantial, and sharing data with Java is fairly expensive, so this should be used only for decent-sized chunks of native code.

In theory, such an extension should be possible, though. One can imagine a Java compiler that targeted a specific platform and allowed assembly escapes. The compiler would have to publish its ABI, so you'd know the calling conventions. I'm not aware of any that do, however. But there are several compilers available that compile Java directly to native code; it's possible one of them supports something like this without my knowing, or could be extended to do so.

Finally, on a different level altogether, there are bytecode assemblers for the JVM, like Jasmin. A bytecode assembler lets you write "machine code" that targets the JVM directly, and sometimes you can write better code than the javac compiler can generate. It's fun to play with, in any event.

like image 192
Ernest Friedman-Hill Avatar answered Oct 04 '22 01:10

Ernest Friedman-Hill


You cannot directly inline assembly in your Java code. Nevertheless, contrarily to what is claimed by some other answers, conveniently calling assembly without going through any intermediary C (or C++) layer is possible.

Quick walkthrough

Consider the following Java class:

public class MyJNIClass {

    public native void printVersion();

}

The main idea is to declare a symbol using the JNI naming convention. In this case, the mangled name to use in your assembly code is Java_MyJNIClass_printVersion. This symbol must be visible from other translation units, which can for instance be achieved using the public directive in FASM or the global directive in NASM. If you're on macOS, prepend an extra underscore to the name.

Write your assembly code with the calling conventions of the targeted architecture (arguments may be passed in registers, on the stack, in other memory structures, etc.). The first argument passed to your assembly function is a pointer to JNIEnv, which itself is a pointer to the JNI function table. Use it to make calls to JNI functions. For instance, using NASM and targeting x86_64:

global Java_MyJNIClass_printVersion

section .text

Java_MyJNIClass_printVersion:
    mov rax, [rdi]
    call [rax + 8*4]  ; pointer size in x86_64 * index of GetVersion
    ...

Indexes for JNI functions can be found in the Java documentation. As the JNI function table is basically an array of pointers, don't forget to multiply these indexes by the size of a pointer in the targeted architecture.

The second argument passed to your assembly function is a reference to the calling Java class or object. All subsequent arguments are the parameters of your native Java method.

Finally, assemble your code to generate an object file, and then create a shared library from that object file. GCC and Clang can perform this last step with a command similar to gcc/clang -shared -o ....

Additional resources

A more comprehensive walkthrough is available in this DZone article. I have also created a fully runnable example on GitHub, feel free to take a look and play around with it to get a better understanding.

like image 36
Pyves Avatar answered Oct 04 '22 02:10

Pyves