如何使用 JNI 从 Java 调用 MEMCMP

发布于 2024-09-26 16:30:38 字数 846 浏览 3 评论 0原文

我需要比较 2 个字节数组并知道哪一个更大或者它们是否相等(仅相等或不同是不够的)。 字节数组表示 15 个或更多字符的字符串值。 这种比较在我的代码中大量重复。

我想通过使用 Java 中 C++ memcmp 方法的等效方法(希望通过 JNI)来改进 bye 数组比较。 我找到了一个在 C# 中使用 DLLImport 的示例,因此我希望 JNI 调用也可以应用。

这是 C# 代码段:

[DllImport("msvcrt.dll")]
    unsafe static extern int memcmp(void* b1, void* b2, long count);

    unsafe static int ByteArrayCompare1(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length)
    {
        CompareCount++;
        fixed (byte* p1 = b1)
        fixed (byte* p2 = b2)
        {
            int cmp = memcmp(p1 + b1Index, p2 + b2Index, Math.Min(b1Length, b2Length));
            if (cmp == 0)
            {
                cmp = b1Length.CompareTo(b2Length);
            }

            return cmp;
        }
    }

有谁知道如何在 Java 中实现它?

提前致谢,

戴安娜

I need to compare 2 byte arrays and know which one is bigger or if they are equal (just equal or different is not enough).
The byte arrays represent a String value of 15 characters or more.
This comparison is repeated considerably in my code.

I would like to improve the bye array compare by using an equivalent of C++ memcmp method in Java (hopefully by JNI).
I found an example to use DLLImport in C#, so I hope a JNI call can be applied as well.

Here is the C# code segment:

[DllImport("msvcrt.dll")]
    unsafe static extern int memcmp(void* b1, void* b2, long count);

    unsafe static int ByteArrayCompare1(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length)
    {
        CompareCount++;
        fixed (byte* p1 = b1)
        fixed (byte* p2 = b2)
        {
            int cmp = memcmp(p1 + b1Index, p2 + b2Index, Math.Min(b1Length, b2Length));
            if (cmp == 0)
            {
                cmp = b1Length.CompareTo(b2Length);
            }

            return cmp;
        }
    }

Does anyone know how to implement this in Java?

Thanks in advance,

Diana

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡墨 2024-10-03 16:30:38

您确定您的代码在这些比较上花费了大量时间吗?我建议现在调用一个Java函数,然后计时;如果还需要,可以添加JNI/JNA。

请记住,通过添加 JNI,您会显着增加出现错误的机会,并且会将您的程序限制为仅适用于您为其编译库的体系结构。

Are you certain your code is spending significant time on those comparisons? I would suggest calling a Java function for now, and then timing it; if you still need to, you can add JNI/JNA.

Remember that by adding JNI you increase your chance of bugs significantly, and you limit your program to only the architectures that you compile the library for.

能否归途做我良人 2024-10-03 16:30:38

可以使用 JNI,但 Java 在 JNI 上有一个变体,称为 JNA (Java Native Access ),它允许您直接访问共享库,而不需要包装它们的 JNI 接口,因此您可以使用它直接访问 memcmp

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

public class Test {
    public interface CStdLib extends Library {
        int memcmp(Pointer s1, Pointer s2, int n);
    }

    public static void main(String[] args) {
        CStdLib c = (CStdLib)Native.loadLibrary("msvcrt", CStdLib.class);
        c.memcmp(...);
    }
}

我没有测试过上面的内容,并且我'我不确定 memcmp 签名,因为它需要 void* 和 size_t ,两者都没有明显的 Java 等效项,但是一些变体应该可以正常工作

(归因:我从

You can use JNI, but Java has a variation on JNI called JNA (Java Native Access), which lets you access shared libraries directly without needing a JNI interface wrapped around them, so you can use that to access memcmp directly:

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

public class Test {
    public interface CStdLib extends Library {
        int memcmp(Pointer s1, Pointer s2, int n);
    }

    public static void main(String[] args) {
        CStdLib c = (CStdLib)Native.loadLibrary("msvcrt", CStdLib.class);
        c.memcmp(...);
    }
}

I've not tested the above, and I'm not sure in particular about the memcmp signature, since it takes void* and size_t, which both don't have obvious Java equivalents, but some variation of that should work correctly

(Attribution: I pulled some of the JNA info from another answer of mine)

风筝有风,海豚有海 2024-10-03 16:30:38

只需使用以下代码,看看它是否足够快。

package so3883485;

import java.util.concurrent.atomic.AtomicLong;

public class ByteArrayUtils {

  static final AtomicLong COMPARE_COUNT = new AtomicLong(0);

  public static int compare(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length) {
    COMPARE_COUNT.incrementAndGet();

    final int commonLength = Math.min(b1Length, b2Length);
    for (int i = 0; i < commonLength; i++) {
      final byte byte1 = b1[b1Index + i];
      final byte byte2 = b2[b2Index + i];
      if (byte1 != byte2) {
        return (byte1 < byte2) ? -1 : 1;
      }
    }

    if (b1Length != b2Length) {
      return (b1Length < b2Length) ? -2 : 2;
    }

    return 0;
  }

}

还有一些单元测试以确保基本案例按预期工作。

package so3883485;

import static org.junit.Assert.*;
import static so3883485.ByteArrayUtils.*;

import org.junit.Test;

public class ByteArrayUtilsTest {

  @Test
  public void test() {
    byte[] bytes = { 1, 2, 3, 4, 5 };
    assertEquals(0, compare(bytes, 0, bytes.length, bytes, 0, bytes.length));
    assertEquals(0, compare(bytes, 0, 0, bytes, 0, 0));
    assertEquals(-2, compare(bytes, 0, 0, bytes, 0, 1));
    assertEquals(2, compare(bytes, 0, 1, bytes, 0, 0));
    assertEquals(-1, compare(bytes, 1, 1, bytes, 2, 1));
    assertEquals(1, compare(bytes, 2, 1, bytes, 1, 1));
  }
}

Just take the following code and see if it is fast enough.

package so3883485;

import java.util.concurrent.atomic.AtomicLong;

public class ByteArrayUtils {

  static final AtomicLong COMPARE_COUNT = new AtomicLong(0);

  public static int compare(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length) {
    COMPARE_COUNT.incrementAndGet();

    final int commonLength = Math.min(b1Length, b2Length);
    for (int i = 0; i < commonLength; i++) {
      final byte byte1 = b1[b1Index + i];
      final byte byte2 = b2[b2Index + i];
      if (byte1 != byte2) {
        return (byte1 < byte2) ? -1 : 1;
      }
    }

    if (b1Length != b2Length) {
      return (b1Length < b2Length) ? -2 : 2;
    }

    return 0;
  }

}

And some unit test to make sure the basic cases work as expected.

package so3883485;

import static org.junit.Assert.*;
import static so3883485.ByteArrayUtils.*;

import org.junit.Test;

public class ByteArrayUtilsTest {

  @Test
  public void test() {
    byte[] bytes = { 1, 2, 3, 4, 5 };
    assertEquals(0, compare(bytes, 0, bytes.length, bytes, 0, bytes.length));
    assertEquals(0, compare(bytes, 0, 0, bytes, 0, 0));
    assertEquals(-2, compare(bytes, 0, 0, bytes, 0, 1));
    assertEquals(2, compare(bytes, 0, 1, bytes, 0, 0));
    assertEquals(-1, compare(bytes, 1, 1, bytes, 2, 1));
    assertEquals(1, compare(bytes, 2, 1, bytes, 1, 1));
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文