我知道Java是一种安全的语言,但是当需要进行矩阵计算时,我可以尝试更快的方法吗?
我正在学习C++、数字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&T风格的x86说明。
发布于 2012-07-24 21:42:30
在Java代码和底层硬件之间有一层抽象层,这使得这种事情在原则上是不可能的;从技术上讲,您无法知道代码在底层机器上是如何表示的,因为同一字节码可以在不同的处理器和不同的体系结构上运行。
您正式可以做的是使用Java Native Interface (JNI)从您的Java代码中调用本机代码。调用开销很大,并且与Java共享数据的开销相当大,因此这应该只用于大小合适的本机代码块。
但从理论上讲,这样的扩展应该是可能的。可以想象一个针对特定平台并允许汇编转义的Java编译器。编译器必须发布它的ABI,这样你就知道调用约定了。然而,我不知道有任何这样做的。但是有一些several compilers available可以将Java直接编译成本机代码;它们中的一个可能在我不知道的情况下支持这样的东西,或者可以扩展到这样做。
最后,在完全不同的层次上,还有用于JVM的字节码汇编程序,例如Jasmin.字节码汇编程序允许您编写直接针对JVM的“机器码”,有时您可以编写比javac编译器生成的代码更好的代码。在任何情况下,玩它都很有趣。
发布于 2017-05-12 06:13:11
您不能在Java代码中直接内联程序集。然而,与一些其他答案所声称的相反,可以方便地调用程序集,而不需要经过任何中间C(或C++)层。
快速演练
考虑以下Java类:
public class MyJNIClass {
    public native void printVersion();
}其主要思想是使用JNI命名约定声明一个符号。在这种情况下,在汇编代码中使用的损坏名称是Java_MyJNIClass_printVersion。该符号必须在其他翻译单元中可见,例如,可以使用FASM中的public指令或NASM中的global指令来实现。如果您使用的是macOS,请在名称前面加上额外的下划线。
使用目标架构的调用约定编写汇编代码(参数可以在寄存器中传递,在堆栈中传递,在其他内存结构中传递,等等)。传递给组装函数的第一个参数是指向JNIEnv的指针,而JNI本身也是指向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和克隆可以使用类似于gcc/clang -shared -o ...的命令来执行最后一步。
其他资源
this DZone article中提供了更全面的演练。我还创建了一个fully runnable example on GitHub,请随意查看并试用它,以获得更好的理解。
发布于 2014-12-31 08:31:47
可以使用Machine Level Java技术从Java中调用程序集。它透明地将用Java编写的汇编代码打包到本机库中,但与最常用的汇编语法非常相似。接下来,您只需要调用一个本机方法,它是在编写程序集的同一个类中定义的。因此,您始终停留在Java环境中,不需要从Java IDE切换到某些汇编工具,然后再切换回Java。
https://stackoverflow.com/questions/11632078
复制相似问题