Skip to content

๐Ÿ“š Learning and exploring how class loading works in the JVM

Notifications You must be signed in to change notification settings

dgroomes/java-class-loading-playground

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

1 Commit
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

java-class-loading-playground

๐Ÿ“š Learning and exploring how class loading works in the JVM.

NOTE: This project was developed on macOS. It is designed for my own personal use.

Overview

How does class loading work? What is the system class loader? What is the effect of two classes, with the same fully qualified name, existing on the classpath? What does it even mean to load a class? Does a class get loaded "into a classloading space" or does a class get loaded into a shared space for the whole process? Does JPMS let us have strong encapsulation of this space?

This codebase is me exploring class loading by way of runnable examples.

Instructions

Follow these instructions to build and run the example program.

  1. Pre-requisite: Java 21
  2. Build the program .jar file:
    • ./gradlew jar
  3. Run the program
    • java -jar build/libs/java-class-loading-playground.jar
    • Study the output and study the code that produced it. You'll see how class loaders can be used to load the same class definition (.class but) twice and it being treated as two different classes at runtime. Interesting!
    • The output looks like this:
      MessageHolder{staticMessage='Hello', classloader='jdk.internal.loader.ClassLoaders$AppClassLoader@63c12fb0'}
      MessageHolder{staticMessage='Hello', classloader='java.net.URLClassLoader@44e81672'}
      
      Logically equal?: false
      Reference-equal?: false
      
      MessageHolder{staticMessage='Goodbye', classloader='jdk.internal.loader.ClassLoaders$AppClassLoader@63c12fb0'}
      MessageHolder{staticMessage='Hello', classloader='java.net.URLClassLoader@44e81672'}
      
      instanceFromAppLoader: MessageHolder{instanceMessage='I'm from the app/system class loader.'}
      instanceFromCustomLoader: MessageHolder{instanceMessage='I'm from a custom class loader.'}
      instanceFromAppLoader type: class dgroomes.MessageHolder
      instanceFromCustomLoader type: class dgroomes.MessageHolder
      instanceFromAppLoader is an instance of MessageHolder
      instanceFromCustomLoader is NOT an instance of MessageHolder
      

Wish List

General clean-ups, TODOs and things I wish to implement for this project:

  • DONE Illustrate the effect of a custom user class loader. Can I load the same class binary twice, with different class loaders, and then print the classes classloader/hashCode to show that are different classes at runtime? What happens to their static fields? This is like some trippy parallel universe stuff. Also, I don't get the difference or the point of the difference between the bootstrap class loader and the system class loader.
    • SKIP Consider dropping .jar files and just outputting and coding to .class files. The reader can make view a .class file in a file explorer whereas a .jar file needs to be unzipped. Remember, this is a demo.

Reference

About

๐Ÿ“š Learning and exploring how class loading works in the JVM

Topics

Resources

Stars

Watchers

Forks

Languages