java:dynamic-class-loader
Table of Contents
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
<project> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>dynamic-loader</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> </manifest> <manifestEntries> <Premain-Class>com.example.DynamicLoader</Premain-Class> <Can-Redefine-Classes>true</Can-Redefine-Classes> <Can-Retransform-Classes>true</Can-Retransform-Classes> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build> </project>
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
java/dynamic-class-loader.txt · Last modified: 2025/01/18 00:08 by odefta