扩展字节缓冲类

2022-09-03 00:50:43

有没有办法创建扩展字节缓冲类的类?

来自ByteBuffer的一些抽象方法是包私有的,如果我创建包java.nio,就会引发安全异常。

出于性能原因,我想这样做 - 例如getInt有大约10个方法调用,以及相当多的if。即使保留所有检查,并且只内联方法调用并删除大/小字节序检查,我创建的测试也表明它可以快4倍左右。


答案 1

你不能扩展ByteBuffer并感谢上帝。

你不能扩展b / c,没有受保护的c-tors。为什么要感谢上帝的部分?好吧,只有2个真正的子类可以确保JVM可以大量优化任何涉及ByteBuffer的代码。

最后,如果您需要实际扩展类,请编辑字节代码,只需将受保护的属性c-tor和公共属性添加到DirectByteBuffer(和DirectByteBufferR)中即可。扩展堆缓冲区没有任何作用,因为您仍然可以访问底层数组

在那里使用并添加自己的类,在你需要的包中扩展(在java.nio之外)。这就是它是如何完成的。-Xbootclasspath/p

另一种方法是使用 sun.misc.Unsafe 并执行您需要的任何操作,并在 之后直接访问内存。address()

出于性能原因,我想这样做 - 例如getInt有大约10个方法调用,以及相当多的if。即使保留所有检查,并且只内联方法调用并删除大/小字节序检查,我创建的测试也表明它可以快4倍左右。

现在好的部分,使用gdb并检查真正生成的机器代码,你会惊讶于会删除多少检查。

我无法想象为什么一个人想要扩展课程。它们的存在是为了允许良好的性能,而不仅仅是OO多晶型执行。


编辑:

如何声明任何类并绕过 Java 验证程序

关于不安全:不安全有2个绕过验证器的方法,如果你有一个扩展ByteBuffer的类,你可以调用其中任何一个。你需要一些被黑客入侵的ByteBuffer版本(但这超级简单),带有公共访问和受保护的c-tor,仅用于编译器。方法如下。您可以使用它们,风险自负。在你像这样声明类之后,你甚至可以使用带有new关键字的类(前提是有一个合适的c-tor)

public native Class defineClass(String name, byte[] b, int off, int len, ClassLoader loader, ProtectionDomain protectionDomain);    
public native Class defineClass(String name, byte[] b, int off, int len);

答案 2

您可以通过使用反射来忽略保护级别,但这会在很大程度上破坏性能目标。

你不能在java.nio包中创建一个类 - 这样做(并以任何方式分发结果)违反了Sun的Java许可证,理论上可能会让你陷入法律麻烦。

我不认为有一种方法可以在不成为本地人的情况下做你想做的事情 - 但我也怀疑你正在屈服于过早优化的诱惑。假设您的测试是正确的(哪些微基准通常不正确):您真的确定访问ByteBuffer将成为实际应用程序中的性能瓶颈吗?当你的应用只花5%的时间在那里,而95%的时间处理它所获取的数据时,ByteBuffer.get()的速度是否可以快4倍,这有点无关紧要。

为了(可能纯粹是理论上的)性能而绕过所有检查听起来不是一个好主意。性能调优的基本规则是“首先使其正常工作,然后使其更快地工作”。

编辑:如果如评论中所述,该应用程序确实在ByteBuffer方法上花费了20-40%的时间,并且测试是正确的,这意味着加速潜力为15-30% - 显着,但IMO不值得开始使用JNI或弄乱API源。我会先尝试用尽所有其他选项:

  • 是否正在使用 -server VM?
  • 是否可以修改应用程序以对ByteBuffer进行更少的调用,而不是尝试加速它确实进行的调用?
  • 使用探查器查看呼叫的来源 - 也许有些是完全不必要的
  • 也许可以修改算法,或者您可以使用某种缓存

推荐