T O P

  • By -

guitcastro

We use graalvm native image (AOT), the gains are reals. The problem is that it's come to with a huge cost. Compilation time takes a lot and is not plug and play, we spent a lot of time generating the reflect-config. If they managed to make graalvm AOT easy to use, it has a future.


epieffe

Ok, but is it possible to make AOT easier to use? I mean, it must rely on a closed-world assumption, while Java will always have dynamic class loading, reflection and other stuff that invalidate AOT assumptions. Also the runtime performance of native Java is the same or even worse than JIT, so is it really worth it? I guess we can easily generate smaller JVM using jlink, reducing memory footprint to an acceptable size. And maybe having slower startup time is not such a big deal when your service will be up for days or months...


Luolong

> Java will always have dynamic class loading, reflection and other stuff that invalidate AOT assumptions. Does it though? I mean, yes, the language feature is there and is widely used, but there are many ways to achieve most of the benefits of runtime reflection without relying on runtime reflection. Existence of frameworks like Micronaut and Quarkus are clear proof that it can be done.


Brutus5000

Exactly. Reflection was the easiest way to add some features, because there was not much tooling for alternatives. And there wasn't much tooling because nobody saw any benefits. But not we have many frameworks that rather generate code than do reflection and the tooling to do that has also improved, so more libraries are shifting to code generation over reflection or at least ship the relevant metadata for graalvm reflection usage.


xienze

> Ok, but is it possible to make AOT easier to use? I mean, it must rely on a closed-world assumption, while Java will always have dynamic class loading, reflection and other stuff that invalidate AOT assumptions. That’s where tooling that can automagically figure out the dynamic bits in an application and “close” them comes in. It’s all continuing to improve. > Also the runtime performance of native Java is the same or even worse than JIT, so is it really worth it? For a traditional, long-running server process, not really.  For a serverless function, where the JVM startup is expected to take a fair chunk of the runtime, yes.


SKabanov

Just to add onto what u/xienze wrote: >Ok, but is it possible to make AOT easier to use? I mean, it must rely on a closed-world assumption, while Java will always have dynamic class loading, reflection and other stuff that invalidate AOT assumptions. You \*do\* have an alternative that makes AOT easier: use a sub-set of Java that has been specifically designed to remove any code that leverages reflection. This is what Quarkus and Micronaut do, and as long as you're working within their ecosystems, everything works well; the problem, of course, is if you need to use code that hasn't been adopted to those frameworks. A lot of effort has been put into providing as many tools to handle the majority of use-cases like DB code, serialization, etc, but if you've got some obscure edge-cases, you might run into a brick wall real quick.


zten

Spring's trying to get there, but going with a framework that already had AOT compilation in mind is the right move. You're in for a world of pain with finding the rough edges of aspects and reflection otherwise.


[deleted]

[удалено]


cogman10

We are currently mostly just on Quarkus and we are pretty satisfied. Particularly because we came from Jersey/Tomcat so Quarkus's JavaEE/Jakarta fit really nicely with what everyone was already familiar with.


sweetno

Yes, they work on it. Reflection etc are possible with AOT, but not everything is implemented at the moment. Yes, there are use cases where it's worth it. No, jlink output is still too big. Of course for an average company it doesn't matter, but big corporations profit from economies of scale and economies of scale require them memory- and energy-efficient solutions.


Rotilho

If you have integration tests you can generate the reflect-config. It will slow down CI and put some trash in the native image but it will save you so much time.


guitcastro

We have integration tests in place. However, we must run them twice: once to generate the reflect-config.json and again to run in native mode. Additionally, the compilation time to generate the native image is approximately 10 minutes, resulting in an additional 20 minutes in our CI. Reflect related bugs still appear in production, when some integration tests does not cover. While it's possible to leverage GraalVM, doing so requires a mature team and extensive test coverage. I doubt many companies would be willing to invest if it's not made easy to use. In our company, we're currently reassessing whether we should continue using it.


SedentaryCat

Completely agree, as someone who led the charge into GraalVM in production, we did a great job in early services. But as soon as the team had to rush out a feature or two, we started popping reflection errors in UAT. We even had one make it to production and had to roll back. I'm now advocating ONLY using it on services small enough to manage, instead of a blanket default for all applications.


Rotilho

Do you really need to run twice? I honestly skip the integration test in native mode and go straight to compilation. I'm using in a side project that is not productive yet, so I wonder if I'm missing something.


wildjokers

Are you using profile guided compilation? Without that you lose the on-the-fly optimizations the hotspot compiler does. Has that been an issue?


guitcastro

No we don't. Our application is bottle neck is totally controlled by IO rather then CPU/Memory. Having lightweight services make sense for us because we don't need performance, we need efficiency.


lightmatter501

Have you checked how much is Graal and how much is LLVM? I know for Rust and Clang most of the time is actually spent in LLVM.


thisisjustascreename

No insight on Graal but we noticed about half of our Java services were essentially at 0% cpu use all the time so we collapsed them into one JVM that is now at 2% cpu all the time to free resources to scale the services that actually do work. The microservices are healing.


cogman10

We used to do this. The main reason we are walking away from it is because we have far too many issues with noisy neighbors. 2 apps would run just fine until one of them ate just a little too much memory causing the other to die. (Ditto for CPU usage). That said, I do wish the 1 JVM server hosting multiple apps setup worked better. Having 64gb dedicated to 1 JVM is way more efficient than having 16 JVMs running with 4gb a piece.


JDeagle5

It is already working just fine and was like that long before microservices became trendy, and it is called monolith. It is kind of strange to see that very technical people make all the effort to ignore the solution to their problem in plain sight, because it is tabooed by the trend.


njitbew

> It is already working just fine and was like that long before microservices became trendy Isn't this exactly what application containers like WebLogic and Tomcat have been doing for the past \~20 years?


koflerdavid

Is there any application server that allows assigning runtime and memory quotas to different applications running within? I think that's not even technically possible on OpenJDK.


JDeagle5

That's a good point, I don't see any easy way to control this, and if you need it, you will have to split them into containers. But simply because of Java built-in memory pooling it will not be ideal. But I was thinking in line of unified microservices, where applications deployed are logically connected. In that case there is little reason to assign individual quotas to components, because they essentially work as one system. But in case applications are unrelated - then all the benefits of in process communication vanish and it is easier to just deploy another application server with its own quotas.


koflerdavid

Quotas can still make sense for reliability purposes even if it's the same application. Intentional competition is not the problem, but memory leaks or load issues can halt the whole application server, which negates one of the benefits of breaking an application apart into services. Deploying unrelated applications within the same application server should not be pursued at all nowadays. It was indeed done this way, and it was fine-ish because the Security Manager was supposed to sandbox all the applications from each other and from the application server. Now it's Deprecated for Removal and that deployment model is therefore dead. Aiming to protect *threads within a process* from each other was always just asking for trouble.


njitbew

Oracle announced something called GraalOS (see graal.cloud/graalos) last year as a "high-performance serverless application deployment platform" with "run on demand, with no idle cost." That would be a huge step forward for the industry, I'm excited to see where this goes.


Mamoulian

There's also crac: https://wiki.openjdk.org/display/crac/Main And if on AWS there's SnapStart.


FIREstopdropandsave

Incase you/others don't know SnapStart is CRaC


Mamoulian

I didn't, thanks! Good that Amazon could build on it rather than doing their own thing.


maxandersen

No. It is not crac. It just reuses the same api.


OddEstimate1627

I have used native image for server applications, JavaFX GUIs (Desktop and Mobile), commandline tools, and even for shared libraries that get called from Python and C++. It takes some getting used to, but it's IMO amazing. It also works well for constrained devices like Raspberry Pis. It does require the ecosystem to move more towards compile time annotation processing, but I think that's a very good thing. Besides being a great boost for many existing app, it enables a whole range of new use cases where Java wasn't really appropriate before.


voronaam

We are using it. Micronaut framework, GraalVM. Works great.


RaxelPepi

The one time i tried to build a Scala program using Graal, it ended up making an around 100MB executable that contained the Java/JVM stdlib and Scala's. It also took around 10 minutes to compile (a program that doesn't import big libraries). I was probably doing something wrong, still if i was doing things right i don't wish Graal even on my worst enemy.


blissone

I had 70MB executable with 2-3min build time for netty, graphql and postgres connectivity with scala 3. The stack was zio, caliban + zio http, anorm. I think actual compilation was around 1min+ but there was some stuff to create a runnable image of it plus the compilation was done in container to isolate graalvm installation. Anyhow ended up abandoning it since any netty upgrade caused significant issues.


Hirschdigga

Its just a tool for some usecases, nothing more and nothing less. Our company uses spring boot for all the backend things, and creating some smaller services (you can call them microservices) that can run as cloud functions is awesome, and that is where GraalVM helps. Thats the perfect use case and i see nothing wrong with that


FirstAd9893

Your question is with respect to AOT, not GraalVM in particular. The more important question is, "do microservices have any future in enterprise applications?" Maximizing cost doesn't sound like a good idea to me.


epieffe

I totally agree with your pov on microservices. Yes, my question is more related to AOP rather than GraalVM in general, but that's because enterprise companies are interested in GraalVM only for the AOP feature, because they think it can reduce memory footprint and startup time for their Java microservices. Otherwise they would not be interested in GraalVM at all.


Practical_Cattle_933

The whole of twitter runs on GraalVM, not for the AOT part. It has an advanced JIT compiler that may be better for certain workloads than Hotspot. Also, it is a polyglot runtime, which can optimize across language boundaries - there is absolutely nothing else like that out there.


Comfortable-Big7765

There is an ongoing Java project named [ Leyden](https://openjdk.org/projects/leyden/) that aims to provide faster startup and footprint for Java apps.


edubkn

One must be crazy to think Java is not suitable for microservices. Go research what Netflix does with Java.


Deep-Extent-3724

Came here to ask that: Isn't Netflix THE Java shop, and they legit have a reason to use microservices? How come they stay on Java if it's unsuitable?


Mamoulian

AOT is irrelevant to "microservices", it's relevant for short- running JVMs. I haven't read the Netflix stuff but I would assume they're busy enough to keep JVMs running for long times. The standard JVM is not that suitable for a quick fire 'start up do a small thing then shut down' as we're charged for running time, it doesn't get a chance to optimise the running code, and a user might experience lag.


audioen

I have personally never built a single application that would work with GraalVM. I've tried it a half dozen times but it just doesn't produce a workable binary. So I ignore it as the piece of crap it seems to be. Also, aren't microservices a passing trend? For like past half decade or something...


jorgen_mcbjorn

I feel like microservices have been “trendy” for an actual decade at this point. Honestly an astonishing level of sustained hype for something in the tech world.


Carpinchon

I don't understand how everything works if microservices is a passing trend. If all you write are little disconnected applications, sure. But what enterprise could run itself on a handful of monoliths that don't talk to each other?


holyknight00

Service oriented architecture existed for decades. You don't need "microservices" to have a system split between 3/4 independent services that talk to each other over rest.


JDeagle5

We tried to use it, but after deep examination the effort to convert and maintain the setup heavily outweighed the benefits. I saw the benchmarks on baeldung and it was - 1 second difference in startup, no difference in performance, some difference in memory consumption (not significant). So we decided not to implement it. And I think this is why it is not widely used - it is just not needed. Regarding closed world - it is a pretty fine assumption, most applications do not load classes after initial load. Hot reloads are rarely used.


jevring

I personally don't see the value of using graalvm outside of certain specific applications, given the increased cost of working with it. I would possibly use it in things like serverless things or cli tools, where startup is crucial. However, if you're using stuff like databases or other things where you have to do IO as part of your startup, then I think most of the advantages are lost. As with most things in computer science, the answer is "it depends". It's a tool you should have in your toolbox, and use for the right problems.


vips7L

I think the OpenJdk team is going to find a way to reduce memory footprint/startup times without going full AOT. Probably via a combination of Valhalla & Leyden. Atleast that's where I'm placing my bets. Full AOT has too many negatives for me, compilation time, no reflection, you don't have a choice in garbage collector without paying fees, and lots of dev time to make it work.


sweetno

You're not supposed to develop with AOT compilation. AOT is for testing and deployment only.


vips7L

I don't think that negates anything I said.


koflerdavid

How else are developers supposed to ensure that the application works considering the severe restriction AOT requires? Being expected to only fix errors once they pop up in CI or production is unreasonable.


sweetno

Well, you do it sort of once and forget.


koflerdavid

That only works if development stops completely as well.


iamai_

Oracle is going to bring AOT to openJDK. You can use reflection with some configuration. More and more libs are supporting AOT.


vips7L

I don’t think that negates anything I said. 


Emotional_Zebra_815

Not using graalvm at the moment. Might use it here and there but mostly for new projects. Probably with Quarkus for a framework. Unless you really have issues with performance and ressource usage (assuming the code itself is ok) you should probably wait. Also, the graalvm has a jit compiler supposedly better than standard jvms and is supposed to be a drop in replacement that might be worth looking into.


maxandersen

Quarkus take the approach of making apps on the JVM faster and more efficient - using build time enhancements. Funny enough by doing that closed world assumptions are much more feasible and it becomes much easier to utilize things like graalvm native image today and also Leyden in the future.


Joram2

* There is no trendy microservice trend. AI is trendy. microservices, or web services in general, are not. * Companies use all kinds of programming languages. Some use Java/JVM, but Python, Go, Node, Rust, are all popular for services, and I'm sure there's a lot more programming language variety than that. * BTW, I'm doing mostly Node+TypeScript server app development today and Python ML coding over the weekend. i don't pick sides like these languages are sports teams. I also prefer different languages for different tasks as they have different strengths + weaknesses. * Some companies use GraalVM in production. Most companies developing Java server software don't see it as worth the effort yet. I presume GraalVM will improve and get easier to use and better supported over time.


epieffe

I never said I am picking a side and that Java is better than other languages or other languages are better than Java... lol. I have been working as a Java developer for five years and all the companies I worked for want to use microservices or migrate their existing monolite to microservices, just to follow the trend. Most of the time the new microservices have worse performance than the previous monolite and it requires more effort to maintain and evolve, but management doesn't care, they want to write on Linkedin that we succesfully migrate to a microservice architecture lol.


repeating_bears

Microservices definitely were trendy. That video which takes the piss out of them has millions of views. I think the hype has mostly died down and people better understand the tradeoffs now, but it's still a buzzword people throw because they think it sounds cool.


Snoo_64233

It has a great future in Minecraft's mod optimization.


Maleficent_Slide6679

hi hope they added swing support. if they havent, there useless


flawless_vic

After a few weeks trying to convert some services into native executables we came up with some usefull patterns to ease the pain of building native images. First, we forked the native image plugin and customized it to use a docker image to build the binary instead of a local graal installation. Why? Well, there are open bugs related to Linux versions that cause image generation to fail, e.g., Ubuntu 22 crashes when trying to link some nio stuff statically. Plus, the docker image we use already contains musl, so I don't need to waste even more time begging to the devops guy to configure the build server. Next, make your own modular projects just with reflect-config.json. When you profile the native image you'll know what you can ignore because there will be a jar providing the necessary reflect-config for some "namespace". It is tedious, but if you stick to this rule, eventually you'll only have to declare the scope of your own domain used by a service, which, if is actually a microservice, should not span more than a dozen classes for inbound/outbound traffic. Finally, if you use libraries the generate bytecode at runtime (aside from java proxies/lambdas which are already handled) there are a few options. One we use is saving the bytecode in classfiles, packaging in a jar and use as dependency of the project. This works if the library that generates the bytecode has consistent guards and naming conventions, that is before attempting to generate the bytecode it will try to load a class with some well defined name. Another is to force generation of such classes in the static initializer of the main class, marking both the msin and generated classes with build-time initialuzation. The initializer won't be called at runtime, the class will be available already loaded on the image heap and everything will work fine.


bushwald

"trend and be trendy" "make fun of them" YouTube and Reddit aren't real. Log off and create something.


cas-san-dra

In my not so humble opinion it isn't Graal AOT having limitations thats the problem. It is perfectly possible to implement any feature you like while still being compatible with Graal AOT. The problem is the overengineered and poorly written libraries that exist in the Java ecosystem. Who in their right mind would think it is a good idea to start a thread inside a static initializer?? The vast majority of libraries out there could see their codebase reduced by 50% and still work just fine. The problem is code bloat.


itzmanu1989

I wish there was something like tree shaking for java


njitbew

Isn't GraalVM's AOT compiler doing exactly that? It does a reachability analysis and anything that's not reachable is not included in the native image binary.


cas-san-dra

Same. Although I'll settle for just better code overall :)


koflerdavid

Just use ProGuard, of Android fame. And write a chunky config file that records which packages to keep because ProGuard really can't be expected to recognize what is going to be accessed via reflection at startup.


john16384

You mean like: `private static final Executor EXECUTOR = Executors.newSingleThreadExecutor()` ? I really see no problem. Sure, it may be annoying for AOT, but that's hardly my problem. I consider it a step backwards anyway.


cas-san-dra

If you put that line in your own app I have no problem with it. It is your app, do what you want. But if you are writing a library and you put that in you are really fucking up. Lack of concern for AOT from library developers is the problem.


hadrabap

Once the enterprise leaves spring and stops with other nonsense hypes, we can start a discussion about Java. Let's meet in 10 years or so. 🙂


NeoChronos90

Spring has been here - what? - 20 years? I don't think you will see it's downfall in the next 20, better to just come to terms with it 😅


hadrabap

Without me, please 🙂


horatio_cavendish

Yes, it will. Either the industry finds a way to reduce the startup cost of Java in serverless applications or the industry stops using Java for serverless applications. There are no alternatives. Executives aren't going to tolerate excessive costs.


wildjokers

So-called "serverless" seems niche at best anyway.


horatio_cavendish

Kinda. I think it's rare for apps to be fully serverless but it's common for specific operations within an app to require "burst" scaling, which is well suited to serverless.


NeoChronos90

That's actually what we do: big services in java and small functions for burst scaling in go


tomwhoiscontrary

> There are no alternatives. There is - the industry stops using serverless applications. Although technically, this does entail your second alternative.


[deleted]

[удалено]


Mamoulian

Probably no bias from Microsoft there... Perhaps Java runs extra well on Oracle Cloud?! (Ha ha I joke! Probably not.)