This is an old revision of the document!
Table of Contents
```java
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
```java 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
1. Compile the class: ```bash javac DynamicLoader.java ```
2. Create the JAR with manifest: ```bash mkdir META-INF # Create MANIFEST.MF with content above jar cfm dynamic-loader.jar META-INF/MANIFEST.MF com/example/DynamicLoader.class ```
With Maven
```xml <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
```bash java -javaagent:dynamic-loader.jar –add-opens java.base/java.lang=ALL-UNNAMED YourMainClass ```
Example Main Class
```java 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 ```