如何使用ASM修改静态变量值?Java Agent新手实操求助
Hey there! I totally get how confusing Java Agents can be when you're starting out—most docs skip over the basic, hands-on details that newbies need. Let's walk through this step by step to modify that x value in your Multiplier class.
1. Quick Primer on Java Agents for Newbies
Java Agents let you modify bytecode before or during your main program's execution. For beginners, the easiest entry point is the premain method: this runs before your main class's main method, giving you a chance to tweak the bytecode.
2. Build Your Agent (With Bytecode Tweaks)
We'll use ASM (a lightweight, widely-used bytecode manipulation library) to modify the x variable—manual bytecode editing is way too error-prone for starters.
Step 2.1: Create the Agent Entry Class
First, make a class that acts as the agent's starting point:
import java.lang.instrument.Instrumentation; public class ModifyXAgent { // This is the mandatory entry point for a premain agent public static void premain(String agentArgs, Instrumentation inst) { // Register a transformer to modify the Multiplier class's bytecode inst.addTransformer(new MultiplierClassTransformer()); System.out.println("Agent loaded successfully!"); // Debug check } }
Step 2.2: Write the Bytecode Transformer
This class will scan the Multiplier class's bytecode and change the value assigned to x:
import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import java.lang.instrument.ClassFileTransformer; import java.security.ProtectionDomain; public class MultiplierClassTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { // Target only the Multiplier class (className uses / instead of .) if ("Multiplier".equals(className.replace("/", "."))) { ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); // Custom ClassVisitor to inspect and modify methods ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) { @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); // Target only the main method (match name and method descriptor) if ("main".equals(name) && "([Ljava/lang/String;)V".equals(descriptor)) { return new MethodVisitor(Opcodes.ASM9, mv) { @Override public void visitIntInsn(int opcode, int operand) { // Find the instruction that pushes 10 (x's initial value) // In bytecode, int x =10; translates to BIPUSH 10 if (opcode == Opcodes.BIPUSH && operand == 10) { // Change 10 to your desired value (e.g., 20) super.visitIntInsn(opcode, 20); System.out.println("Modified x's value from 10 to 20!"); } else { super.visitIntInsn(opcode, operand); } } }; } return mv; } }; cr.accept(cv, ClassReader.EXPAND_FRAMES); return cw.toByteArray(); } // Leave other classes untouched return classfileBuffer; } }
Step 2.3: Get ASM Dependencies
Since we're using ASM, download these two JARs and add them to your Eclipse project:
asm.jar(core ASM library)asm-commons.jar(optional but simplifies some operations)
3. Package the Agent into a JAR
Eclipse needs a custom manifest to recognize this as a Java Agent:
- Create a
MANIFEST.MFfile in your project's root with this content:
Premain-Class: ModifyXAgent Can-Redefine-Classes: true
- Export your agent project as a JAR, making sure to include the manifest and ASM classes (or keep ASM JARs separate and add them to the classpath later).
4. Run Your Main Program with the Agent
Open a command prompt and run this command (replace paths with your actual JAR locations):
java -javaagent:path/to/ModifyXAgent.jar -jar path/to/Multiplier.jar
You should see output like:
Agent loaded successfully! Modified x's value from 10 to 20! Multiply of x*y = 500
Key Tips for Newbies
- Check Bytecode with
javap: Runjavap -c Multiplier.classin your terminal to see the raw bytecode of your main class. This helps you match the exact instructions you need to modify (likeBIPUSH 10forint x=10). - Debug First: Add print statements in your agent to confirm it's loading correctly before troubleshooting bytecode issues.
- ASM Version Match: Use the latest stable ASM version (like ASM9) to avoid compatibility bugs with newer Java versions.
内容的提问来源于stack exchange,提问作者LEON

