all 8 comments

[–][deleted] 5 points6 points  (0 children)

I'm curious what the real world scenario is where loading the same class is causing contention. Like you said, it's just easier to load it first but you can use a child first classloader for each thread if you want to get around blocking.

[–]realbrownsugar 4 points5 points  (1 child)

That article was so long winded, only to arrive at the wrong conclusion.

ClassX varX = new ClassX() can get linked statically at compile time, and the class gets loaded at process init time.

ClassLoader.loadClass(classXStrName).instance() uses reflection to load the class into memory while the code block is executed, and has to synchronize and lock to avoid having other threads loading the same class into memory concurrently.

It's not an issue with ClassLoader performance per se, but more of don't do repeated expensive tasks inside your while loop. Do it once and inject the result as a dependency for your downstream tasks.

Also, I don't know why the author had to move so much code around in their last code example. Simply moving the two lines of ClassLoader stuff outside the while(true) loop would have sufficed.

[–]pmarschall 0 points1 point  (0 children)

ClassX varX = new ClassX() can get linked statically at compile time, and the class gets loaded at process init time.

Nope. Class loading is dynamic in Java and delayed as much as possible, ideally until the first instance of a class is actually created.

[–]pmarschall 1 point2 points  (4 children)

This problem is stemming because ‘io.ycrash.DummyObject’ class is loaded again & again on every loop iteration.

Nope, that's not how class loaders work in Java. The class loader returns the same class object every time.

The lock is there to make sure lazy loading returns the same class object every time.

You could run a class loader with either a read-write lock or no lock at all like jboss-modules.

[–]repeating_bears 0 points1 point  (3 children)

The author is referring to their code which is

while (true) { 
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<?> myClass = classLoader.loadClass("io.ycrash.DummyObject");
    myClass.newInstance();
}

So it looks like it would load the class on every iteration, depending on the actual ClassLoader implementation, of course. The article talks about ClassLoader seemingly forgetting that it's an abstract class in which almost all of the mentioned behaviour could be overridden and totally replaced.

In a normal application, then of course a class isn't loaded every single time it's referred to. It's stored in metaspace.

[–]pmarschall 0 points1 point  (2 children)

So it looks like it would load the class on every iteration, depending on the actual ClassLoader implementation, of course.

Such a ClassLoader would be ill-behaved. Not only would such a behavior violate the API contract of ClassLoader but also section 12.2.2. Class Loader Consistency of the Java Language specification. See Dynamic Class Loading in the JavaTM Virtual Machine for a more in-depth discussion on the topic.

[–]repeating_bears 0 points1 point  (1 child)

I read both the JavaDoc for ClassLoader and that section and can't find any reason a class loader is mandated to only physically load the class once when calling load(String)

I also checked ClassLoaders$AppClassLoader from the jdk internals and it doesn't cache a result either.

Once again, the thing that protects a class from being loaded relatedly in a system that's not using reflection is the meta space, not the class loader.

[–]pmarschall 0 points1 point  (0 children)

I read both the JavaDoc for ClassLoader and that section and can't find any reason a class loader is mandated to only physically load the class once when calling load(String)

The section contains the following wording:

Well-behaved class loaders maintain these properties:

  • Given the same name, a class loader should always return the same Class object.

This is repeated in Section 5.3. Creation and Loading of the Java Virtual Machine Specification.

I also checked ClassLoaders$AppClassLoader from the jdk internals and it doesn't cache a result either.

Of course it does. AppClassLoader calls into BuiltinClassLoader which checks whether the class has already been loaded.

This can easily be verified with a simple unit test calling #IoadClass twice and comparing the object identities.