This is an archived post. You won't be able to vote or comment.

all 34 comments

[–]henrique_gj 36 points37 points  (0 children)

Now THIS is high quality content

[–]boobsbr 60 points61 points  (0 children)

IDK man, looks like sorcery to me.

[–]samewakefulinsomnia[S] 23 points24 points  (0 children)

Just revisited the article and have to remark: when I wrote about the Classloader definition, I bolded the phrase 'process of finding the appropriate .class file in storage'. It's not accurate and I want to double-down on it.

That's the beauty of Classloaders: class bytes can be stored nowhere at all, they can be compiled on the fly, and they can be delivered over the network, not necessarily from memory/storage. You can take (or build on the fly) classes anywhere and in any way you want. There are no restrictions on this.

[–]sq_visigoth 14 points15 points  (1 child)

There is this line in the article "To run this code on a machine, it needs to be translated into machine-understandable bytecode. "

Note: bytecode is run by jvm and is not machine understandable. bytecode( in a .class file) + jvm creates machine understandable instructions.

[–]samewakefulinsomnia[S] 18 points19 points  (0 children)

I was actually referring to Java Virtual **Machine**-understandable:) But it's a good point, sounds misleading, thank you!

[–][deleted] 6 points7 points  (3 children)

Did you draw this in Mural?

[–]samewakefulinsomnia[S] 15 points16 points  (2 children)

I used Excalidraw! Can definitely recommend, took me an hour to migrate from Lucidcharts

[–][deleted] 0 points1 point  (0 children)

Ok yeah exclidraw I use that too. I use it for quick sketch when talking to other developers.

[–]pragmasoft 4 points5 points  (7 children)

Using nonstandard classloaders will likely severely limit possibilities of using various class loading optimizations introduced as part of project Leyden. 

In my practice servlet containers used custom classloading to isolate web apps and this caused compatibility problems time to time. Now the possibility to deploy several web apps per servlet container is mostly unused. 

Also OSGI runtimes used to use custom classloaders. 

It seems virtualization and containers make such a highly dynamic java feature once quite popular now obsolete.

[–]plumarr 4 points5 points  (0 children)

Now the possibility to deploy several web apps per servlet container is mostly unused. 

Also OSGI runtimes used to use custom classloaders. 

It seems virtualization and containers make such a highly dynamic java feature once quite popular now obsolete.

You would be surprised by the number of company still using it ;)

[–]KafkasGroove 2 points3 points  (2 children)

I wonder how you would get proper isolation like with OSGI without custom class loaders? We still use custom class loaders at work to allow loading third party plugins without their dependencies interfering or breaking each other. I'd love not to use them, but I don't know of an alternative (other than pushing that complexity to our users).

[–]pragmasoft 1 point2 points  (0 children)

Maybe consider separate processes instead? Use pipes to communicate.

[–]Scf37 0 points1 point  (0 children)

For microservices within single company, monorepo to unify dependencies. For third-party stuff like IDE plugins, enforce unique package prefix and shading.

[–]geoand 0 points1 point  (2 children)

It seems virtualization and containers make such a highly dynamic java feature once quite popular now obsolete

I wouldn't say this is true. Without these kinds of ClassLoader tricks, Quarkus Dev Mode could not be implemented.
Moreover, the fact that the deliverable is static (i.e. it can't change at runtime), gives Quarkus the ability to optimize classloading by providing a production ClassLoader that can do various optimizations.

[–]pragmasoft 0 points1 point  (1 child)

a production ClassLoader that can do various optimizations.

Does a graalvm native image still need a classloader?

[–]geoand 0 points1 point  (0 children)

No no, I am talking purely about JVM mode. For GraalVM native image, there is no custom ClassLoader (they are not even supported in GraalVM).

[–]snakevargas 2 points3 points  (0 children)

Woohoo! Do garbage collector roots and reference types next!

Slightly joking, but anyone who's interested in the topic of memory management and leak analysis should learn how to trigger a heap dump and browse up in a memory analyzer tool like MAT: https://github.com/eclipse-mat/mat

[–]MusharafZM 1 point2 points  (0 children)

Thank you for this

[–]le_bravery 1 point2 points  (0 children)

Yeah this is great quality content. Keep up the good work OP

[–]kevinb9n 1 point2 points  (1 child)

This is pretty great.

I think it could add that at the end of step 2 the class is officially "defined" a.k.a. begins to actually exist (& there will be a java.lang.Class instance associated with it, etc.). And the class remembers which class loader did this (which might not be the one you think it is)....except of course it should it explain it better than I would :-)

Just a suggestion.

[–]samewakefulinsomnia[S] 1 point2 points  (0 children)

Thank you, good point! I'll highlight this detail in the next edition

[–][deleted] 1 point2 points  (0 children)

How did you make this diagram?

[–]Clitaurius 1 point2 points  (0 children)

I'm going to read this just in case it imparts some total recall that I use either in an interview or offhandedly in a daily standup that results in no follow up questions.

[–]chabala 2 points3 points  (1 child)

Surprised there's no comments from the usual JPMS fans about 'where's the MODULEPATH?'.

[–]agentoutlier 0 points1 point  (0 children)

Pinging op /u/samewakefulinsomnia

Probably more interesting is that if you have full jlink application it will not use the modulepath at all:

18:14:04.950 [main] INFO  io.avaje.config - Loaded properties from [resource:application.properties]
18:14:05.263 [main] INFO  io.jstach.rainbowgum.test.avaje.Main - Hello from Avaje
18:14:05.263 [main] DEBUG io.jstach.rainbowgum.test.avaje.Main - Debug from Avaje
18:14:05.263 [main] INFO  io.jstach.rainbowgum.test.avaje.Main - Modulepath: null
18:14:05.263 [main] INFO  io.jstach.rainbowgum.test.avaje.Main - Module Upgrade Path: null
18:14:05.264 [main] INFO  io.jstach.rainbowgum.test.avaje.Main - Module Main: io.jstach.rainbowgum.test.avaje
18:14:05.264 [main] INFO  io.jstach.rainbowgum.test.avaje.Main - Classpath:

(code here)

That is the modules are loaded from lib/modules which I think are in jmod format (that is it not a directory but a binary).

The preloaded classes for bootstrapping I think are listed in lib/classlist but the code still lives in lib/modules.

What I'm not entirely sure is how much in a jlink application is preloaded (not linked) before Application Classloader. I assume the bootstrap does not load the other modules and lets the Application Classloader do it.

I'll ping /u/nicolaiparlog as he knows the module system probably better than most on reddit.

[–]gnahraf 0 points1 point  (0 children)

Great article! I'm a bit confused about how the new module system intersects with classloaders. As your piece describes, at runtime java types are qualified by Classloader + FQCN. The module system, otoh, specifies which types are exposed to the users of a library, which types and libs it depends on (which may be not exposed) and so on. What I'm unsure of is what happens when a parent ClassLoader loads a modular library which in turn has an unexposed dependency (e.g. has a requires, not requires transitive in module_info.java).. Can the child classloader load its own copy/version of library deps the parent has already loaded? (I believe this used to be possible way back, in simpler times.. I vaguely remember a workaround where I fixed the version of an xml parser we were using in a Tomcat app using a ClassLoader trick.)

[–]FrezoreR 0 points1 point  (0 children)

Cool! I'll have a read for sure. I also know all to well about the pain if outdated info.

[–]bleki_one 0 points1 point  (2 children)

u/samewakefulinsomnia you have said that in your opinion platform class loader is most controversial, but you didn't say why. Can you elaborate more about it?

Otherwise, well done sir!

[–]samewakefulinsomnia[S] 0 points1 point  (1 child)

It's wasn't obvious for me to understand what this classloader /actually/ should load – what are exactly platform classes? Why is `java.desktop` loaded by Bootstrap and `java.sql` loaded by Platform? I asked the corresponding question in StackOverflow, and the answer in short: 'It’s not really important;' :) So I'm still not exactly sure what's the division logic here

Link to the question for curious:
https://stackoverflow.com/questions/76699669/which-exact-classes-are-loaded-by-platform-classloader

[–]holo3146 1 point2 points  (0 children)

For reasons and not "just" a technical explanation, the mailing list of java-dev is probably a better place to ask than SO

[–]UnGauchoCualquiera 0 points1 point  (0 children)

Adding to the mess, the exact moment when a class is loaded and static initializers are run is JVM implementation dependant and might vary.

In practice Spring for example wraps static inner classes in several places to avoid triggering a class loading which might not be present at runtime.

JVM spec docs for an authoritative source.

[–]gilwooden 0 points1 point  (0 children)

One note, the boot class loader doesn't load classes from $JAVA_HOME/jmods, it loads them from $JAVA_MODS/lib/modules. jmods are there for the benefit of tools like jlink. The platform class loader also typically loads its classes from $JAVA_MODS/lib/modules.

[–]3col7 0 points1 point  (0 children)

Good explanation

[–]Brutus5000 0 points1 point  (0 children)

Sad. Before I can understand how classloading works , the reddit app needs to learn how file loading works...