====== Dynamic Classpath Loading with Java Instrumentation ====== ===== Overview ===== Starting with Java 9, the recommended way to modify the classpath at runtime is using Java Instrumentation. This approach works with the Java Module System and is production-ready. ===== Implementation ===== ==== Basic Agent Class ==== package com.example; import java.lang.instrument.Instrumentation; import java.util.jar.JarFile; public class DynamicLoader { private static Instrumentation instrumentation; public static void premain(String args, Instrumentation inst) { instrumentation = inst; try { // Load specific jar inst.appendToSystemClassLoaderSearch(new JarFile("libs/mylib.jar")); // Or load all jars from a directory File libDir = new File("libs"); if (libDir.isDirectory()) { for (File jar : libDir.listFiles((dir, name) -> name.endsWith(".jar"))) { inst.appendToSystemClassLoaderSearch(new JarFile(jar)); } } } catch (IOException e) { e.printStackTrace(); } } } ==== MANIFEST.MF ==== Manifest-Version: 1.0 Premain-Class: com.example.DynamicLoader Can-Redefine-Classes: true Can-Retransform-Classes: true ===== Building ===== ==== Without Maven ==== javac DynamicLoader.java mkdir META-INF # Create MANIFEST.MF with content above jar cfm dynamic-loader.jar META-INF/MANIFEST.MF com/example/DynamicLoader.class ==== With Maven ==== 4.0.0 com.example dynamic-loader 1.0-SNAPSHOT 17 17 org.apache.maven.plugins maven-jar-plugin 3.2.0 true com.example.DynamicLoader true true ===== Running ===== ==== Basic Usage ==== java -javaagent:dynamic-loader.jar --add-opens java.base/java.lang=ALL-UNNAMED YourMainClass ==== Example Main Class ==== public class MainApp { public static void main(String[] args) { // Classes from dynamically loaded jars are now available MyDynamicClass instance = new MyDynamicClass(); instance.doSomething(); } } ===== Important Notes ===== * The agent must be loaded before the main class * The --add-opens argument is required for Java 9+ * The agent jar must be accessible when starting the JVM * Error handling should be implemented for production use ===== Common Issues ===== * **ClassNotFoundException**: Verify jar path and manifest * **SecurityException**: Check --add-opens arguments * **InvalidJarException**: Ensure jar files are valid ===== Best Practices ===== * Log all loaded jars * Implement proper error handling * Document the loading process * Test with all target Java versions * Consider security implications ===== Example Directory Structure ===== project/ │ ├── src/ │ └── main/ │ └── java/ │ └── com/ │ └── example/ │ └── DynamicLoader.java │ ├── libs/ │ ├── mylib1.jar │ └── mylib2.jar │ ├── pom.xml └── README.md ===== References ===== * [[https://docs.oracle.com/en/java/javase/17/docs/api/java.instrument/java/lang/instrument/Instrumentation.html|Java Instrumentation API]] * [[https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/jar/JarFile.html|JarFile Documentation]]