1. Steps to reproduce
1) Write the java class to be compiled
package f_asm_and_javassist; import jdk. internal .org.objectweb.asm.* ; import java.io. * ; import static jdk. internal .org.objectweb.asm.Opcodes.ASM5; /* * * @Author zhangboqing * @Date 2020/3/26 */ public class AsmDemo { // Methods and fields to access the class public static void main(String[] args) { byte [] bytes = getBytes(); // Byte array of the MyMain.class file ClassReader cr = new ClassReader(bytes); ClassWriter cw = new ClassWriter( 0 ); ClassVisitor cv = new ClassVisitor(ASM5, cw) { @Override public FieldVisitor visitField( int access, String name, String desc, String signature, Object value) { System. out .println( " field: " + name); return super.visitField(access, name, desc, signature, value); } @Override public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions) { System. out .println( " method: " + name); return super.visitMethod(access, name, desc, signature, exceptions); } }; cr.accept(cv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG); } private static byte [] getBytes() { StringBuilder sb = new StringBuilder(); try (FileInputStream fileInputStream = new FileInputStream( new File( " MyMain.class " )); BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)) { byte [] buffer = new byte [ 1024 * 8 ]; while (bufferedInputStream.available()> 0 ) { int length = bufferedInputStream.read(buffer); sb.append( new String(buffer, 0 ,length) ); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return sb.toString().getBytes(); } }
2) Use javac to compile in the current directory
javac -d. AsmDemo.java
Prompt the following error:
➜ f_asm_and_javassist git:(master) ✗ javac- d. AsmDemo.java AsmDemo.java: 3 : error: package jdk. internal .org.objectweb.asm does not exist import jdk. internal .org.objectweb.asm.* ; ^ AsmDemo.java: 7 : error: package jdk. internal .org.objectweb.asm does not exist import static jdk. internal .org.objectweb.asm.Opcodes.ASM5; ^ AsmDemo.java: 7 : error: static import only from classes and interfaces import static jdk. internal .org.objectweb.asm.Opcodes.ASM5; ^ AsmDemo.java: 18 : error: cannot find symbol ClassReader cr = new ClassReader(bytes); ^ symbol: class ClassReader location: class AsmDemo AsmDemo.java: 18 : error: cannot find symbol ClassReader cr = new ClassReader(bytes); ^ symbol: class ClassReader location: class AsmDemo AsmDemo.java: 19 : error: cannot find symbol ClassWriter cw = new ClassWriter( 0 ); ^ symbol: class ClassWriter location: class AsmDemo AsmDemo.java: 19 : error: cannot find symbol ClassWriter cw = new ClassWriter( 0 ); ^ symbol: class ClassWriter location: class AsmDemo AsmDemo.java: 20 : error: cannot find symbol ClassVisitor cv = new ClassVisitor(ASM5, cw) { ^ symbol: class ClassVisitor location: class AsmDemo AsmDemo.java: 20 : error: cannot find symbol ClassVisitor cv = new ClassVisitor(ASM5, cw) { ^ symbol: class ClassVisitor location: class AsmDemo AsmDemo.java: 20 : error: cannot find symbol ClassVisitor cv = new ClassVisitor(ASM5, cw) { ^ symbol: variable ASM5 location: class AsmDemo AsmDemo.java: 33 : error: cannot find symbol cr.accept(cv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG); ^ symbol: variable ClassReader location: class AsmDemo AsmDemo.java: 33 : error: cannot find symbol cr.accept(cv, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG); ^ symbol: variable ClassReader location: class AsmDemo 12 errors
2. the solution
This is the limitation of javac. By default, javac will not read classes from rt.jar. It is read from a symbol file that contains only standard APIs and some internal APIs (such as com.sun., com.oracle. and sun. *).
To disable this mechanism, you can use javac -XDignore.symbol.file=true
With maven, you can use:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgument>-XDignore.symbol.file</compilerArgument> </configuration> </plugin>
The above problem can be successfully executed with the following command:
javac -XDignore.symbol.file=true -d. AsmDemo.java
For the class to be package name, you need to use -d., which means that the package path is automatically generated in the current directory