Master the fundamental concepts of jvm internals through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksClasses enter the JVM through class loaders arranged in a parent-delegation tree. Bootstrap loads core JDK classes; platform and application loaders handle modules and your classpath.
Delegation model: a loader asks its parent first, then searches its own path. This prevents application code from replacing \`java.lang.String\`.
Custom loaders (OSGi, Spring Boot fat jars) override \`findClass\` to load bytes from non-standard locations.
For example, loading \`com.example.App\` walks loaders until one finds \`com/example/App.class\` bytes, defines the class, and links it.
Breaking delegation by loading `java.lang` classes from an application loader is a security bug. Custom loaders still ask the parent for core classes before searching their own JARs.
This exercise asks you to document bootstrap, platform, and application loaders and the delegation order. You will explain how \`ClassLoader.loadClass\` resolves names before your mini-JVM loads its first class.
You will use the same mental model here when reading production interpreter source later in the track. Sketch one concrete input on paper, predict the outcome, then confirm with code. That discipline catches logic errors early and makes debugging far faster when you extend the implementation in follow-on tasks.
Simulate the JVM's class loaders:
java/*;Print every delegation step.
java/lang/Object, java/lang/String (extends Object), java/util/AbstractList (extends Object), java/util/ArrayList (extends AbstractList).java/sql/Date and javax/sql/DataSource, both extending Object.provide.# starts a comment.
cLoading…
load(L, C) at depth d, indenting each trace line 2·d spaces; the top level is depth 1)L: cached C (defined by D), and return D.java/*, and C is on L's path: L: child-first, found locally, then define.L: delegate to P, then load(P, C) at depth d+1. If that succeeds, cache C in L and return. If a definition failed, fail too.L: not found.Define C in L:
java/* class defined by any loader other than bootstrap or platform fails with L: SecurityException: prohibited package name java.L: define C, then (if C has a super S) L: resolve superclass S followed by load(L, S) at depth d+1. On failure, print L: NoClassDefFoundError: S and fail.Every loader that sees a successful result caches it. That makes it an initiating loader.
cLoading…
=> C defined by D, => ClassNotFoundException: C or => failed to define C.init: L has not loaded C). The state belongs to the runtime class (its defining loader's entry).
C (D) already initialized.initialize C (defined by D).same runtime class: C defined by D, or different runtime classes: C1@D1 vs C2@D2 (casting one to the other throws ClassCastException). It uses each loader's cache (else same: L has not loaded C).L: … lists the cache in load order, with * marking classes defined by another loader, or none.loader prints loader NAME (parent P[, child-first]).loader: NAME PARENT [child-first], loader X: already exists, loader X: too many loaders (8)provide: LOADER CLASS [extends SUPER]load: LOADER CLASS, init: LOADER CLASSsame: LOADER CLASS LOADER CLASSclasses: LOADERunknown command XInput:
cLoading…
Output:
cLoading…
Hidden tests cover a child-first loader shadowing an app class (and the resulting ClassCastException), java/* protection, a parent-first loader where the app's copy wins, a missing superclass, initialization across loaders, and command errors.