98 comments

[ 2.7 ms ] story [ 114 ms ] thread
> The JEP is a Preview Feature meaning the Foreign Function & Memory API (hereafter "FFM") will not be a final feature in JDK 21. I think some of us hoped it could make it into finality in 21. However, my personal opinion is that the API is very unlikely to change in any significant way and what we are seeing in 21 will be very close to the final FMM API.

One thing I really appreciate about Java and the JEP process is the careful attention to detail and avoid breaking changes. So if it takes a few extra cycles, I'm all in. It's worth getting it right the first time.

FFS, stuff I downloaded from Node _5m ago_ is already deprecated.

Yeah. this is one of the main reasons I use Java for most of my work. The time spent putting out fires caused by framework- and library churn is time not building something useful.
My first exposure to programming, the AP CS exam (and its accompanying course), was in java. My first hobby foray into programming (Minecraft) was Java. So, I'm heavily biased here by my familiarity. However, in the years since, I've done a lot of time where my primary focus at jobs was, among others: python data stuff, "fullstack" stuff, Scala stuff, and golang stuff. And I just keep coming back to Java as my overall favorite.

My personal diff against most languages goes something like:

1. Stuff rots a lot less fast than in python and js. Code keeps working for longer, dependency goofiness happens a lot less, etc.

2. It's just less clunky than golang - but this is mostly my own preferences. I often describe go as if someone designed a language, and then had this list of hard language design problems, and were I to look at this list, I would go "hmm yes these are hard problems where all the options have drawbacks", and then for EVERY SINGLE ONE OF THEM they picked the compromise I would not have picked. So it's just death by a thousand little things that annoy me. My current job is golang though so I'm wondering if I'll come around to it or something. We shall see.

3. Java just doesn't encourage such terrible cleverness that Scala (and to a lesser extent python and js) invites. This might be cultural too where Scala has this functional programming fanatics segment who love the cats library a little too much. But never have I ever before seen so much code that's just intractable to junior devs, and requires far too much brain-CPU for mids and seniors to read. Sure you can get into a lot of trouble with Java's reflection, but IME many java devs are suitably reluctant to go reflection crazy.

4. Damn is it fast by default. And can be REALLY fast if you specifically focus on a specific path.

5. The tooling is so mature. Does python or go even have anything like VisualVM? And as I understand it, even VisualVM is old hat compared to JFR, though I've not looked closely there.

6. The library ecosystem. It's even more expansive then npm but 10x less thrashy and churny. I particularly like that there's this interesting niche of academic libraries that end up out there that you might find yourself bumping into now and then.

7. Packaging. People use maven. Even people who use gradle still basically are just using maven with extra steps. Sure it's XML but aside from adding dependencies, you hardly touch it. And if your build system truly needs to be weird (like, say, android), then gradle is right there for you. 2 tools for the whole ecosystem. How many does python have again? I find I have little patience for packaging problems and I suspect some of it stems from the fact that if I were using Java, I wouldn't be having packaging problems.

I'm sure I could go on, but I'll cut it here. For a million reasons, I find stuff built in Java just works and keeps working (both dev-environment and in prod) far more probably and for longer than in other languages and stacks. And it's fast enough to develop that I'd say it's well within range of python and ruby and such, for anything that bigger than a couple files.

As someone who mostly does small hobby projects I do really like how easy the packaging is in Python and JS is. To get started you literally just do “npm i” or “pip install” whereas Maven and Gradle are a bit of a pain to configure in comparison
True but beyond hobby projects this becomes a double-edged sword that swings back at you.
Could it not have both? Can’t something work like Maven or Gradle but have some nice utility commands to make installing things easy? Or does that already exist?
What did you learn first, npm or Maven/Gradle?

I started in Java land, and to me, the idea that you would run a command to add a dependency has always seemed a bit weird. The file with dependencies in is part of the source code, and i don't want to modify it at arm's length with a command any more than i want to write code that way.

also fwiw, while xml is kind of not very pretty, for most dependencies, you literally google "mydependency maven", click the first link, click the version you want, then literally just copy/paste the XML into your pom.xml.

Is it as slick as 1 command? No. But it's certainly not rocket science, and most libraries github readmes even provide you the maven <dependency /> blob, so it's not usually confusing imo. And also, I do want to point out that "just npm -i mything" comes with problems like typosquatting, which is a lot less common in java afaik.

This is a dinosaur opinion, wow.

Would you also avoid generating client types for type-safe API consumption because you have to run a command to do that instead of writing the client yourself? After all, the client is source code for the client

I don't see these as comparable at all.
Say more.

My package.json is part of source code. I can manually write it myself and run `npm install` afterwards; or I can do both steps via a command. The end result is identical: my package.json has a new package, and my local machine has a copy of that package somewhere too.

Why wouldn't I use the command, exactly?

> The end result is identical

Citation needed.

Installing npm dependencies in different orders is not garanteed to be deterministic due to npm's package flattening and, before npm 8, plain broken dependency resolution strategy.

The package-lock.json is essential to get the same mess that the initial developer got on the same order as his install.

> and my local machine has a copy of that package somewhere too.

On maven/gradle, like on pnpm, you get one copy of each library. Not 3000x copies of lodash spread around your disk.

> > The end result is identical

> Citation needed.

What do you mean? You cited it yourself:

> Installing npm dependencies in different orders

Fortunately, there is no difference in order between running it as a command and adding it and running `yarn install`, since you already had all the other packages locally either way.

Anyways, these complaints are ridiculous, I'm sure I could dig into the past and find some broken Maven or Gradle resolutions. Let's see, 10 second time limit:

> gradle.lockfile

LOL wow.

> 3000x copies of lodash spread around your disk

LOL

Modifying text files that are human readable are a big no-no. Generating files that you never touch is absolutely ok (and is a huge thing in Java, mind you, starting from annotation processors).
> Modifying text files that are human readable are a big no-no.

Silly absolutes are a big no-no. You don't use automatic code formatting!?

Using commands to modify a literal list is fine.

I probably learned npm or pip first so I guess it depends on what you’re used to

But with npm you can still modify the package.json and it feels simpler than than the Maven XML still (though I have no idea what’s going on with the package_lock file, but I don’t think you’re meant to edit that manually)

Yes especially in an education setting where the level of overhead of Maven/Gradle for a student just learning to program is too high.
IntelliJ has a dependency browser GUI that can edit your Maven/Gradle builds, but yes you're right, the CLI tooling from other ecosystems is nicer. Unfortunately the lack of robustness isn't. Just today I was debugging a sudden failure of a Python script because someone released a new version of a dependency of a dependency of a dependency which for some reason just fails to install on Ubuntu 20 without a proper error message. In the JVM world there's no such thing as a failure to install a library, because there's no install process at all, and you don't need lockfiles or any of these other hacks to avoid stuff breaking.
Lol, what? NPM is amazing
For stress testing file operations?
For my Java projects, to support different environments - corp proxies, let's say - I have to have entire different gradle files, plugins, options, routing, it's just disgusting.

For my JS projects (obviously actually TS these days), I use the exact same config, it's parametrizable to take in one argument - the private registry to use.

It's amazing for really using. Unlike Java package managers.

Gradle literally creates a configuration from a script, which it can later use to build the project. It is absolutely trivial to use different proxies in different environment based on env vars, local files, etc.

Gradle is not too liked (android's overly complex builds probably give it a bad name), but it is an absolutely capable build system.

> It is absolutely trivial to use different proxies in different environment based on env vars, local files, etc.

For something to be "absolutely trivial", you would expect the average user to be able to produce trivial-looking configuration. It is certainly not the case with any Java program I've seen which has to handle two build environments.

On the other hand, all my NodeJS projects show absolutely no sign they had to be "adapted" to the second+ environment.

But sure, we can pretend Java package management is up to snuff, just throw some more "it's trivial"-type aphorisms around

IME npm sucks even more that Java if you really need to change repositories ( not just proxy ).

I was stuck under very old (and deprecated) versions of node and NPM, and at my $OLDJOB lockfiles were respected with a CI under restrictive proxy service and alternative npm repo.

"delete lockfile, npm install everything again with correct repository under VPN" was a very recurring thing on every project where someone thought "it's just a npm install, what could go wrong?".

Have you tried using profiles?

Maven supports build profiles.

Spring and other frameworks also supports runtime profiles, where you can have a YAML file for each profile/environment

The root of this thread is the person I responded to claiming NPM, as an easy-to-use package manager, would "become a double-edged sword that swings back at you"

Meanwhile, you are having to tell me Java package management is actually better because... it has profiles

I think that Java guys might have their heads too far up their asses

No, we have just worked with huge enterprise applications for 20 years and attempted to get the build system right a few times already, learning from previous attempts — as opposed to creating some mess of ad-ridden (seriously — having terminal ads, are we crazy?!!), slow (windows literally chokes up on deleting the node_modules folder, which is not a rare operation), displaying some insane number of vulnerabilities no matter what, which is also due to having way too many too small packages, and every one bringing in a huge deal of other bullshit tiny dependencies.

Oh, did you know that maven wasn’t hit by those dependency confusion attacks, being almost alone in that? Also, I can literally build a million lines repo faster than the frontend which is relatively small and just outputs goddamn js and css files..

> Also, I can literally build a million lines repo faster than the frontend which is relatively small and just outputs goddamn js and css files..

My UI type-checks, transpiles, and stores itself as an NGINX container or a static bundle on my CI in 1min10, so I'm going to go ahead and press X to doubt.

> windows

There's your problem!

These downvotes are absurd.

The parent comment asserts, without evidence, that "NPM being easy to use is a double-edged sword that will swing back at you".

I have never seen any evidence of this in action. What would it even mean!? Something being easy to use being casted as a negative in-and-of-itself sounds like Stockholm Syndrome.

If you'll downvote a long-time NPM user for questioning what's wrong with NPM given how much better it is at navigating the complex corporate environment I sit in than Gradle or Maven, at least leave an anecdote.

It's all on you. You brought npm into the discussion which was until then quite generic comparing java builds against "others". You barge into a thread of people praising a certain ecosystem by defending your own turf and trying to convince everyone that your tools are actually ok. What did you expect? Sure bro, use npm, whatever.
How is it "on me" that stupid "opinions" are being expressed?

First of all, the context was:

my initial comment's GP: "I do really like how easy the packaging is in Python and JS is", "Maven and Gradle are a bit of a pain to configure in comparison"

my initial comment's parent: "True but beyond hobby projects this becomes a double-edged sword that swings back at you."

This comment CONTINUES to be a naked assertion based on nothingness. The negative points about NPM I've heard are:

* You should never touch human-readable files with CLIs (like package.json)

* NodeJS imports make many files because it's interpreted code

* running a command to install a package is "weird" and doing it manually is better

* Something about module resolution that was fixed half a decade ago but still didn't impact most shops that avoided drowning in libraries

You can't be serious that this is meaningful feedback.

> stupid "opinions"

Whatever the subject, I expect people who like a certain tech to express their distaste about other techs. I just, you know, let it slide cause otherwise it's never over. If you're looking for a bone to chew, I'd suggest you go to Reddit. Seriously.

I like Scala and I really recognise that terrible cleverness, but I really don't like you blaming it on the language because it's a failure of people.

(Conversely, I really really wish I'd done my personal project in Scala rather than C#. It manages to be good and horrible at the same time)

I don't really believe that you can separate the language from how it's used. I blame Java when people write code that beats the crap out of the GC because Java both makes it easy (especially with streams sometimes) and also is flippant about it in most recommendations (which emphasize that the gc is good, allocating an object is cheap, and so on). Python somehow doesn't seem to have that happen nearly as often, for instance.

So I also blame Scala when people over-use implicits and go functional-mad because Scala encourages it.

> Python somehow doesn't seem to have that happen nearly as often, for instance.

It really is not a sarcastic comment, but Python is just not that fast to make GC the performance bottleneck in ordinary usage. It uses ref counting, which trades off performance to a more deterministic deallocation (plus there is also the GIL).

One of Scala's biggest mistakes was probably to support higher rank types, because it seems to have resulted in a in a hostile takeover of the Scala community by pure FP zealots. No one in the world ever thought: "why don't I write Haskell code on top of a VM that really isn't well-optimized for it, using a language that wasn't designed at all for it?" But that seems to be what a large portion of the community does nowadays.

This wasn't Scala's only mistake though. It seems to have a history of implementing features that then die out due to a combination of lack of support and of never being implemented well in the first place, including:

* specialized types

* macros

* delimited continuations

* Scala reflection

* Eclipse IDE support

* Scala native (technically still going but only whenever there is funding at a university to pay a student to work on it)

* Multiple collections library rewrites (this one is pretty core!)

* other half-baked bundled libraries that have been deprecated/removed over time

Not to mention the number of community-owned frameworks that have been discontinued or declined in usage over time. Anyone remember Lift? That used to be the most popular web framework in Scala! And how are Play Framework and Akka doing nowadays?

Well, sure Scala is a more "language research-y" PL compared to Java, but I do think that with the recent revamp of Scala 3 they did a very good job. Also, that overly zealous FP trend seems to have died down a bit, and a pragmatic FP approach is probably the most idiomatic (e.g. local mutability, but mostly immutable public APIs), which is probably the best of both worlds.

I also firmly believe that Scala has hands-down the very best collections API out of any single language I have used, so there is that.

It's been years (7? 8? geez) since I've written Scala but has macro support really died out? Is this a 2 vs 3 thing?

I remember loving it and saw a plenty of other community libraries leaning on it. I had some simple reflection based code I rewrote using macros for a big performance bump. The API was awkward and forced me to learn more of the magic under the covers, but in the end I was happy with it. I figured it would be too deeply ingrained and useful to just go away.

> 3. Java just doesn't encourage such terrible cleverness that Scala (and to a lesser extent python and js) invites. This might be cultural too where Scala has this functional programming fanatics segment who love the cats library a little too much. But never have I ever before seen so much code that's just intractable to junior devs, and requires far too much brain-CPU for mids and seniors to read. Sure you can get into a lot of trouble with Java's reflection, but IME many java devs are suitably reluctant to go reflection crazy.

Java has improved significantly in this regard, but Java used to be the poster child for overly clever intractable code. It mostly been relagated to memes and legacy code, but AbstractFactoryFactory used to be the way of writing Java code, where everything was supposed to happen through a dozen layers of indirection.

For sure. I do speak of Java mainly from what I've seen in the past, say, decade. Where it does seem like we've mostly learned our collective lesson there.
Ive been programming Java since around 1.4 and that AbstractFactoryFactory meme is just BS. Its not in the language. Some frameworks were bloated in that way but that's not the language.
If your build system requires more than what Maven can do, I'd say it's time to go home and rethink your life choices. All that Gradle does is allow you to create an unfixable spaghetti mess. Adapt your project to Maven, write your own plugins and extensions if you must. Don't. Use. Gradle.
Say what you will about the evil database company which shall not be named, but under their stewardship the JVM ecosystem is moving into the right direction, and there is massive investment in foundational technologies that will take years to come to fruition, some of it unmatched (eg virtual threads or GraalVM).
Out of curiosity, what's the difference between virtual threads, green threads and, say, goroutines?
Its solving the function colouring issue. Your code can run against old-school OS-threads with blocking I/O, or it can run against virtual threads with non-blocking I/O that look and behave almost exactly the same, but are multiplexed onto fewer underlying OS threads, without needing to introduce language constructs such as async/await or changing anything in your program code except maybe the executor implementation.

Golang is opinionated towards its single coroutine model, there is no way to switch. Its a good model and it works well, but there are cases where it leaks, such as low-performance C interop.

Green threads usually refer to single-threaded runtimes such as Node.

So it's basically an implementation of transparent of M:N scheduling, right?

I remember that early versions of Rust had that but dropped it because building a single implementation of that that scales to all platforms is hard (tm).

Yep, M:N cooperatively scheduled. It also requires a "runtime" which Rust didn't want to have
Green threads usually refer to single-threaded runtimes such as Node.

This doesn't sound right. How is the single-threaded event-loop of node green threads?

Apart from that, it makes a lot of sense to have multiple threads in Node. They just run in the background, do stuff, and send events into JS land from time to time.
Not a lot. To a large extent, they are different names for the same concept. But since they are the names used for that concept by specific implementations, they also imply the particularities of those implementations.

The old Java green threads could only use a single core, the new Java virtual threads can use multiple cores. AFAIK, Java green and virtual threads are both cooperatively scheduled, Goroutines are, nowadays, preemptively scheduled. And so on and so forth.

Java's virtual threads are preemptive, not cooperative -- they are preempted not at explicit points, but at blocking IO operations.
If you can’t break a thread out of an infinite loop, that is pure cpu and no io, then the run time is not preemptive, surely??
At worst the OS will preempt the thread and the JVM will likely schedule a different virt thread the next time — but in case you have multiple CPU-hungry virtual threads fighting over a single core it will suck no matter what. The performance improvement comes from doing useful work on a thread during IO waits.

Nonetheless, there were discussions about some way to force preemption at certain points, not sure whether there is a decision since, but that will be the exception, not the rule.

Still trying to understand: what's the difference between "forc[ing] preemption" and cooperative threading?
In cooperative threading, a thread can only be suspended when it interacts with the runtime - so when it does I/O, or yields, or uses a lock, or maybe does some reflection, or perhaps allocates, or whatever. In preemptive threading, a thread can be suspended anywhere.

There is a bit of a grey area in between, where threads can be suspended outside the runtime, but not anywhere. Go had this for a while - threads could get suspended on function entry too.

If you've got a thread that's in a loop in which it doesn't allocate, doesn't call other functions, doesn't interact with the runtime in any way, maybe it's just looping over huge arrays of numbers doing calculations, then a cooperative threading runtime can't suspend it, whereas a preemptive threading runtime can.

But we're talking about forcing preemption, which is basically calling into the runtime, isn't it?
The terminology you're using doesn't really make sense to me, so i don't understand what you're asking, i'm afraid.

In cooperative multithreading, a thread only enters the runtime when that is part of its normal program flow. The code it's executing does I/O, or acquires a lock, or something like that. In preemptive multithreading, some mechanism can force any thread into the thread scheduler at any time.

If you climb back the chain, you'll see

> Nonetheless, there were discussions about some way to force preemption at certain points, not sure whether there is a decision since, but that will be the exception, not the rule.

I'm trying to understand the difference between "forcing preemption" and requesting for the runtime to yield, the latter being an operation typical in cooperative multithreading.

> they are preempted not at explicit points, but at blocking IO operations.

That is cooperative scheduling.

People tend to forget that it was Oracle alongside IBM, that joined Sun in the major Java push before anyone else. See Network Computer, first Swing based GUI for DBAs, SP in Java,...

Both of which also have had their own JVM implementations.

Virtual Threads are actually in their second preview which means it might not be years before we see them standard in the JDK.
It currently looks like Virtual Threads will be final in JDK 21, to be released in September this year.

https://openjdk.org/jeps/8303683

Just to be clear that's a submitted draft JEP [1] so not quite there yet....

[1] https://openjdk.org/jeps/1

But it is not the first iteration, and the loom branch has working versions for quite some times now. It’s definitely not in a design-only phase.
Loom was already merged into their master equivalent, iirc. It was shipping behind a preview flag for a while.
(comment deleted)
> FFS, stuff I downloaded from Node _5m ago_ is already deprecated.

There's really no reason to use hyperbole to make your point. And besides, Node and Java aren't very different in their release policies. Node follows a standard LTS structure where every other release is an LTS, and Java follows a standard LTS structure where every third release is an LTS. If anything, that means more versions of Node are supported for longer without backwards incompatible changes.

The comment isn't about the language but the ecosystem, which yes it's hyperbole, but seems to generally hold true. The node ecosystem has a ton of churn
No, the comment is clearly about the language. The literal context of the submission is a new API being added to Java, and the GP is discussing how they prefer the slow pace of evolution of Java to Node's supposed breakneck pace of breaking changes.

Unfortunately, they're just making up things about Node, thus my comment explaining how they're incorrect.

My first thought was “What about JNA?”

> Over the years, numerous frameworks have emerged to fill the gaps left by JNI, including JNA, JNR and JavaCPP. These frameworks are often a marked improvement over JNI but the situation is still less than ideal — especially when compared with languages which offer first-class native interoperation. For example, Python's ctypes package can dynamically wrap functions in native libraries without any glue code. Other languages, such as Rust, provide tools which mechanically derive native wrappers from C/C++ header files.

Is this JEP going to make that possible in Java?
I believe the goal of this project is to provide a low-level API for FFI, on which other tools can build.

Not sure which part of the quoted text you are asking about specifically, but it is quite likely possible to build such an abstraction on top of it (plus Java's dynamic class loading + loading dynamic libs should be able to handle pretty much any case). For an example, jextract is also in the works that will generate Java helper classes from C headers.

Thanks. Sorry for being unclear - I was talking about importing a C header.
Yet another feature Android will miss out.
It's a shame. Android _should have_ from the beginning used: Linux containers, a modified JVM profile, Android libraries as regular java dependencies, etc.
At least they updated Android 12 to Java 11 LTS, and Android 14 will get Java 17 LTS.

However it is a subset as usual, and most likely because they are already starting to feel that Kotlin also needs those Java libraries which are leaving Java 8 behind, unless they feel like rewriting Maven Central universe into Kotlin.

You seem to be knowledgeable about the Android situation - what’s the current deal? From what I gathered, android uses a hybrid runtime that has many parts of the code AOT compiled and cached, but can JIT compile as well to suit for a particular device, is my understanding correct?

But yeah, I agree with you, they really should have gone with possibly a simpler JIT compiler and an alternative GC implementation that is more conservative in memory usage.

What's wrong with the current one?
Here for the JIT/AOT, since Android 7 (5 and 6 used AOT only), https://source.android.com/docs/core/runtime/jit-compiler?hl...

The issue isn't even converting JVM bytecodes into DEX, other compliant Java implementations for embedded do similar approaches, see PTC and Aicas.

The issue is how they have stagnated Java support on purpose as means to push Kotlin, they aren't being innocent by using Java 8 samples against Kotlin features.

And the whole but Oracle doesn't cut it, given how dependent Kotlin is on the whole JVM ecosystem.

It starts that way, with a mark and sweep collector (think Java CMS or the GC of Go). But some applications like games or Facebook are monsters so the GC was changed to a copy collector which has a better throughput, avoid fragmentation at the cost of using more memory.

Also the code is not just AOTed, Android is using profile guided AOT. After several days of usage, the code is AOTed with the profile collected from previous runs.

Java on Android is a miserable experience because of how far behind it is. That you can't really guarantee that anything past Java 1.7 is available means that everyone just writes to that lowest common denominator (of course, there's plenty of legacy code too…)
Yes, how else would they push their Kotlin agenda, if modern Java was given the same access.

See how little everyone cares on the JVM, it is just another guest language alongside Scala, Clojure and Groovy competing for attention.

I don't really understand your comment.

- What do they win by pushing Kotlin against Java (for reasons that are not also beneficial to developers)? The word "agenda" makes it seem like they have evil intents

- Doesn't Kotlin depend on the JVM, and so wouldn't it benefit from an upgrade

- Isn't Kotlin a programming language that uses the JVM and the Java standard library anyway? (I saw a bit of Kotlin, I contributed a small patch to QKSMS, it seems it is a bit like Groovy in that it is an alternative syntax but is essentially Java with some syntax sugar and some additional classes to make some tasks easier)

I understand that Kotlin may not directly benefit from the new Java language features, but it seems like it would benefit from all the other advances.

(I'm not defending Google, I don't like them)

Kotlin is a safety net because Google/Android vs Oracle (the lawsuit).
Not really, because Kotlin is useless without JVM ecosystem.

InteliJ/Android Studio, Gradle and Maven Central libraries.

Kotlin/Native was so well done that they had to reboot the effort.

If they cared about so much, they should have migrated to Dart instead.

It's just a diversion? We're using Kotlin and not Java? The fact that Kotlin uses Java is then Kotlin's problem (so to speak).
I don't see Groovy competing for attention. People who want to have a Rails like development experience on the JVM is a completely different market than the usual Spring Boot stuff or legacy code that still uses xml hibernate definitions. Yes, I still have to deal with that.

Also the Java codebase is significantly slower because raw Hibernate is terrible and should never be combined with JSF.

Meanwhile with grails your only performance worry is that each field plugin template is its own class, which puts immense pressure on the class loader which has to do the non envious job of loading a thousand classes.

Despite significant amounts of indirection and excessive use of hidden reflection to abstract over entity/domain classes, the parts I expected to be slow are never the ones you would expect. CompileStatic, etc is almost never worth it.

Groovy competes more with Ruby than with Java.

Guest languages compete among themselves.

They will never replace Java on the Java Virtual Machine.

Is Groovy still going strong? I do like the idea of it (at the very least for using groovy files for JPA entities), but unfortunately have seen less and less of it.
Unfortunately the application we develop (speech assistant) also needs to run on Android (head units) and that is really frustrating
This is an intricate API that is likely to require an intricate implementation just to be correct. But correctness won't be enough, the JEP requires the JIT to implement some complex optimizations.

I could use some reflections around: how do you implement such a large and complex feature in a JIT without potentially creating lots of vulnerabilities. It looks like a lot of new surface area in the VM with bad failure modes and VM engineers too are only human.

How is the overhead of each function call in this implementation? I'm wondering if it's significantly more efficient to manipulate a struct in foreign memory directly than to call a bunch of foreign setter functions. This may influence how I eventually implement a Java binding for AccessKit [1].

[1]: https://github.com/AccessKit/accesskit

This is interesting and a nice thing to have built into the JVM.

It seems to me though that SubstrateVM[1] makes calling native functions even easier (from page 8 of the slides):

    // C:
    struct timespec {
      __time_t tv_sec;
      __syscall_slong_t tv_nsec;
    };
    int clock_gettime(clockid_t __clock_id, struct timespec *__tp)

    // Java:
    @CStruct interface timespec extends PointerBase {
      @CField long tv_sec();
      @CField long tv_nsec();
    }
    @CFunction static native int clock_gettime(int clock_id, timespec tp);
[1]: https://www.complang.tuwien.ac.at/lehre/ubvo/substrate.pdf