我知道Java是一种安全的语言,但是当需要进行矩阵计算时,我可以更快地尝试一下吗?
我在C ++,Digital-Mars编译器和FASM中学习__asm {}。我想在Java中做同样的事情。如何在函数中内联汇编代码?这甚至可能吗?
像这样的东西(使用AVX支持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]);
我不想使用代码注入器。我想看看英特尔或AT&amp; T风格的x86指令。
答案 0 :(得分:14)
在Java代码和底层硬件之间有一层抽象,原则上使这种事情变得不可能;从技术上讲,你不知道你的代码是如何在底层机器上表示的,因为相同的字节码可以在不同的处理器和不同的架构上运行。
您正式可以做的是使用Java Native Interface(JNI)从您的Java代码调用本机代码。调用开销很大,并且与Java共享数据相当昂贵,因此这应该只用于体面大小的本机代码块。
理论上,这种扩展应该是可能的。可以想象一个针对特定平台并允许程序集转义的Java编译器。编译器必须发布其ABI,因此您将了解调用约定。但是,我不知道有什么用。但是several compilers available可以直接将Java编译为本机代码;可能其中一个人在我不知情的情况下支持这样的事情,或者可以扩展到这样做。
最后,在一个不同的层面上,JVM有字节码汇编程序,如Jasmin.字节码汇编程序允许您编写直接面向JVM的“机器代码”,有时您可以编写比javac
编译器可以生成。无论如何,玩它很有趣。
答案 1 :(得分:7)
您无法在Java代码中直接内联汇编。然而,与其他一些答案所声称的相反,可以方便地调用汇编而无需通过任何中间C(或C ++)层。
快速演练
考虑以下Java类:
public class MyJNIClass {
public native void printVersion();
}
主要思想是使用JNI命名约定声明符号。在这种情况下,要在汇编代码中使用的错位名称为Java_MyJNIClass_printVersion
。此符号必须在其他翻译单元中可见,例如可以使用FASM中的public
指令或NASM中的global
指令来实现。如果您使用的是macOS,请在名称前加一个下划线。
使用目标体系结构的调用约定编写汇编代码(参数可以在寄存器,堆栈,其他内存结构等中传递)。传递给汇编函数的第一个参数是指向JNIEnv
的指针,它本身是指向JNI函数表的指针。用它来调用JNI函数。例如,使用NASM并定位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
...
JNI函数的索引可以在Java documentation中找到。由于JNI函数表基本上是一个指针数组,不要忘记将这些索引乘以目标体系结构中指针的大小。
传递给汇编函数的第二个参数是对调用Java类或对象的引用。所有后续参数都是本机Java方法的参数。
最后,汇编代码以生成目标文件,然后从该目标文件创建共享库。 GCC和Clang可以使用类似于gcc/clang -shared -o ...
的命令执行最后一步。
其他资源
this DZone article中提供了更全面的演练。我还创建了一个fully runnable example on GitHub,随时可以查看并使用它来更好地理解。
答案 2 :(得分:2)
可以使用Machine Level Java技术从Java调用程序集。它透明地将用Java编写的汇编代码打包到本机库中,但与最常用的汇编语法非常相似。接下来,您只需要调用一个本机方法,您可以在同一个类中定义程序集的编写位置。因此,您始终处于Java环境中,无需从Java IDE切换到某些组装工具,然后再切换回Java。
答案 3 :(得分:1)
您无法直接从Java调用程序集。但您可以通过JNI调用C代码,然后从那里调用程序集。
答案 4 :(得分:1)
您使用JNI或JNA并从Java调用本机函数。或者作为替代方案,您将字节码作为InputStream并从中创建Java类。
答案 5 :(得分:1)
您可能还希望查看Aparapi。