> First, primitive operations for crypto are intrinsics in Java and operate without FFI at all.
This is a pretty strange assertion given that I didn’t specify the crypto operation I wanted to perform. Is XAES-256-GCM available in the Java standard library?
> Doing it this way is not so common in Java anyway
Sure, because doing it the other way would be very expensive. But that doesn’t mean applications which can’t front or backload native processing don’t exist, it just means they will have slower throughput in Java.
It’s fine for a language to make that tradeoff, but it is a tradeoff
> Is XAES-256-GCM available in the Java standard library?
No (is it in any language's standard library?) but everything you need to implement it in Java is available.
> But that doesn’t mean applications which can’t front or backload native processing don’t exist, it just means they will have slower throughput in Java.
They won't, because working with native memory is just as efficient as working with heap memory. You store your bytes in a MemorySegment and you don't care if it's backed by an on- or off-heap buffer. I guess you could say, oh, but when working with FFI in Java you may need to keep some buffers off-heap if you don't want to copy bytes, but that's common practice in Java since JDK 1.4 (2002).
> It’s fine for a language to make that tradeoff, but it is a tradeoff
There is a tradeoff, but it's not on performance. Rather than expose Java heap objects directly to native code (which is possible with the old JNI, but not the recommended approach), Java says keep the bytes that you want to efficiently pass to native code off-heap and makes it easy to do (through the same interface for on- and off-heap data).
Rather than constrain the implementation, which could have performance implications always, Java gives you the choice to have no FFI overhead at the cost of a tiny bit of convenience when doing FFI. Given how rare FFI is in Java compared to many other languages, that is obviously the right design decision and it helps performance rather than harms it. So there is a tradeoff, but you're clearly trading away less than you would have if FFI were more common and the core implementation were impacted by it.
Ultimately, the question of "is it better to sacrifice language performance and flexibility in exchange for doing X (without significant performance overhead) in 3 lines instead of 30" depends entirely on the answer to the question how often users of the language need to do X. If the language is Java and X is FFI, the answer is "rarely" and so you're paying a small cost for a large gain. The tradeoff between the convenience of low/no-overhead FFI and language performance and flexibility becomes much more difficult and impactful in languages where FFI is more common.
This is a pretty strange assertion given that I didn’t specify the crypto operation I wanted to perform. Is XAES-256-GCM available in the Java standard library?
> Doing it this way is not so common in Java anyway
Sure, because doing it the other way would be very expensive. But that doesn’t mean applications which can’t front or backload native processing don’t exist, it just means they will have slower throughput in Java.
It’s fine for a language to make that tradeoff, but it is a tradeoff