扩展ByteBuffer类

Sar*_*mun 14 java nio bytebuffer

有没有办法创建扩展ByteBuffer类的类?

ByteBuffer的一些抽象方法是包私有的,如果我创建包java.nio,则抛出安全异常.

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

bes*_*sss 13

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

你不能延长b/c没有受保护的c-tors.为什么感谢上帝?那么,只有2个实子类确保JVM可以优化了涉及ByteBuffer的任何代码.

最后,如果你需要扩展类的实际,编辑字节代码,只需将c-tor和public属性的protected属性添加到DirectByteBuffer(和DirectByteBufferR).扩展HeapBuffer无论如何都没有任何意义,因为无论如何都可以访问底层数组

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

另一种方法是使用sun.misc.Unsafe并做任何你需要的事情,然后直接访问内存address().

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

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

我无法想象为什么一个人想要扩展课程.它们的存在是为了获得良好的性能而不仅仅是OO多态执行.


编辑:

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

On Unsafe:Unsafe有2个绕过验证程序的方法,如果你有一个扩展ByteBuffer的类,你可以调用它们中的任何一个.对于编译器,你需要一些带有公共访问和受保护的c-tor的ByteBuffer的黑客版本(但这非常简单).方法如下.你可以自己承担风险.在宣布类之后你甚至可以使用w/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);
Run Code Online (Sandbox Code Playgroud)


Mic*_*rdt 9

您可以通过使用反射来忽略保护级别,但这有点大大地击败了性能目标.

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

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

想要绕过所有检查(可能纯粹是理论上的)性能并不是一个好主意.性能调优的基本规则是"首先让它正常工作,然后让它更快地工作".

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

  • 你在使用-server VM吗?
  • 是否可以修改应用程序以减少对ByteBuffer的调用,而不是试图加快它所做的那些?
  • 使用分析器查看呼叫的来源 - 可能有些是完全没必要的
  • 也许可以修改算法,或者你可以使用某种缓存


Tof*_*eer 2

ByteBuffer 是抽象的,所以,是的,您可以扩展它......但我认为您想要做的是扩展实际实例化的类,而您可能无法扩展它。也可能是实例化的特定方法重写了该方法,从而比 ByteBuffer 中的方法更有效。

我还想说,对于所有需要的内容,您可能总体上是错误的 - 也许这不是您正在测试的内容,但代码的存在可能是有原因的(也许在其他平台上)。

如果您确实认为自己是正确的,请打开一个错误并看看他们怎么说。

如果你想添加到 nio 包中,你可以尝试在调用 Java 时设置启动类路径。它应该让你把你的类放在 rt.jar 类之前。输入 java -X 查看如何执行此操作,您需要 -Xbootclasspath/p 开关。

  • ByteBuffer 具有包私有抽象 _set 和 _get 方法,因此您无法覆盖它。而且所有构造函数都是包私有的,因此您无法调用它们。 (3认同)
  • “你可以扩展它”对我来说并不是说“如果你把你的子类放在 bootclasspath 上,你就可以扩展它”。如果你弄乱了靴子,那么你可以做你想做的事。非常接近我的-1... (3认同)