parent
ac9cfefaff
commit
185c2bf5b6
|
@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public abstract class AnnotationVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public AnnotationVisitor(final int api) {
|
public AnnotationVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
|
@ -67,13 +67,13 @@ public abstract class AnnotationVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param av
|
* @param av
|
||||||
* the annotation visitor to which this visitor must delegate
|
* the annotation visitor to which this visitor must delegate
|
||||||
* method calls. May be null.
|
* method calls. May be null.
|
||||||
*/
|
*/
|
||||||
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
this.api = api;
|
this.api = api;
|
||||||
|
|
|
@ -104,7 +104,7 @@ final class AnnotationWriter extends AnnotationVisitor {
|
||||||
*/
|
*/
|
||||||
AnnotationWriter(final ClassWriter cw, final boolean named,
|
AnnotationWriter(final ClassWriter cw, final boolean named,
|
||||||
final ByteVector bv, final ByteVector parent, final int offset) {
|
final ByteVector bv, final ByteVector parent, final int offset) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
this.cw = cw;
|
this.cw = cw;
|
||||||
this.named = named;
|
this.named = named;
|
||||||
this.bv = bv;
|
this.bv = bv;
|
||||||
|
|
|
@ -222,6 +222,8 @@ public class ClassReader {
|
||||||
// case ClassWriter.CLASS:
|
// case ClassWriter.CLASS:
|
||||||
// case ClassWriter.STR:
|
// case ClassWriter.STR:
|
||||||
// case ClassWriter.MTYPE
|
// case ClassWriter.MTYPE
|
||||||
|
// case ClassWriter.PACKAGE:
|
||||||
|
// case ClassWriter.MODULE:
|
||||||
default:
|
default:
|
||||||
size = 3;
|
size = 3;
|
||||||
break;
|
break;
|
||||||
|
@ -365,7 +367,9 @@ public class ClassReader {
|
||||||
break;
|
break;
|
||||||
// case ClassWriter.STR:
|
// case ClassWriter.STR:
|
||||||
// case ClassWriter.CLASS:
|
// case ClassWriter.CLASS:
|
||||||
// case ClassWriter.MTYPE
|
// case ClassWriter.MTYPE:
|
||||||
|
// case ClassWriter.MODULE:
|
||||||
|
// case ClassWriter.PACKAGE:
|
||||||
default:
|
default:
|
||||||
item.set(tag, readUTF8(index, buf), null, null);
|
item.set(tag, readUTF8(index, buf), null, null);
|
||||||
break;
|
break;
|
||||||
|
@ -572,11 +576,14 @@ public class ClassReader {
|
||||||
String enclosingOwner = null;
|
String enclosingOwner = null;
|
||||||
String enclosingName = null;
|
String enclosingName = null;
|
||||||
String enclosingDesc = null;
|
String enclosingDesc = null;
|
||||||
|
String moduleMainClass = null;
|
||||||
int anns = 0;
|
int anns = 0;
|
||||||
int ianns = 0;
|
int ianns = 0;
|
||||||
int tanns = 0;
|
int tanns = 0;
|
||||||
int itanns = 0;
|
int itanns = 0;
|
||||||
int innerClasses = 0;
|
int innerClasses = 0;
|
||||||
|
int module = 0;
|
||||||
|
int packages = 0;
|
||||||
Attribute attributes = null;
|
Attribute attributes = null;
|
||||||
|
|
||||||
u = getAttributes();
|
u = getAttributes();
|
||||||
|
@ -617,6 +624,12 @@ public class ClassReader {
|
||||||
} else if (ANNOTATIONS
|
} else if (ANNOTATIONS
|
||||||
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
|
||||||
itanns = u + 8;
|
itanns = u + 8;
|
||||||
|
} else if ("Module".equals(attrName)) {
|
||||||
|
module = u + 8;
|
||||||
|
} else if ("ModuleMainClass".equals(attrName)) {
|
||||||
|
moduleMainClass = readClass(u + 8, c);
|
||||||
|
} else if ("ModulePackages".equals(attrName)) {
|
||||||
|
packages = u + 10;
|
||||||
} else if ("BootstrapMethods".equals(attrName)) {
|
} else if ("BootstrapMethods".equals(attrName)) {
|
||||||
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
|
int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
|
||||||
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
|
for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
|
||||||
|
@ -645,6 +658,12 @@ public class ClassReader {
|
||||||
classVisitor.visitSource(sourceFile, sourceDebug);
|
classVisitor.visitSource(sourceFile, sourceDebug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// visits the module info and associated attributes
|
||||||
|
if (module != 0) {
|
||||||
|
readModule(classVisitor, context, module,
|
||||||
|
moduleMainClass, packages);
|
||||||
|
}
|
||||||
|
|
||||||
// visits the outer class
|
// visits the outer class
|
||||||
if (enclosingOwner != null) {
|
if (enclosingOwner != null) {
|
||||||
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
|
classVisitor.visitOuterClass(enclosingOwner, enclosingName,
|
||||||
|
@ -714,6 +733,120 @@ public class ClassReader {
|
||||||
classVisitor.visitEnd();
|
classVisitor.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the module attribute and visit it.
|
||||||
|
*
|
||||||
|
* @param classVisitor
|
||||||
|
* the current class visitor
|
||||||
|
* @param context
|
||||||
|
* information about the class being parsed.
|
||||||
|
* @param u
|
||||||
|
* start offset of the module attribute in the class file.
|
||||||
|
* @param mainClass
|
||||||
|
* name of the main class of a module or null.
|
||||||
|
* @param packages
|
||||||
|
* start offset of the concealed package attribute.
|
||||||
|
*/
|
||||||
|
private void readModule(final ClassVisitor classVisitor,
|
||||||
|
final Context context, int u,
|
||||||
|
final String mainClass, int packages) {
|
||||||
|
|
||||||
|
char[] buffer = context.buffer;
|
||||||
|
|
||||||
|
// reads module name, flags and version
|
||||||
|
String name = readModule(u, buffer);
|
||||||
|
int flags = readUnsignedShort(u + 2);
|
||||||
|
String version = readUTF8(u + 4, buffer);
|
||||||
|
u += 6;
|
||||||
|
|
||||||
|
ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
|
||||||
|
if (mv == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// module attributes (main class, packages)
|
||||||
|
if (mainClass != null) {
|
||||||
|
mv.visitMainClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packages != 0) {
|
||||||
|
for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
|
||||||
|
String packaze = readPackage(packages, buffer);
|
||||||
|
mv.visitPackage(packaze);
|
||||||
|
packages += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads requires
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String module = readModule(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
String requireVersion = readUTF8(u + 4, buffer);
|
||||||
|
mv.visitRequire(module, access, requireVersion);
|
||||||
|
u += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads exports
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String export = readPackage(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
int exportToCount = readUnsignedShort(u + 4);
|
||||||
|
u += 6;
|
||||||
|
String[] tos = null;
|
||||||
|
if (exportToCount != 0) {
|
||||||
|
tos = new String[exportToCount];
|
||||||
|
for (int j = 0; j < tos.length; ++j) {
|
||||||
|
tos[j] = readModule(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitExport(export, access, tos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reads opens
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String open = readPackage(u, buffer);
|
||||||
|
int access = readUnsignedShort(u + 2);
|
||||||
|
int openToCount = readUnsignedShort(u + 4);
|
||||||
|
u += 6;
|
||||||
|
String[] tos = null;
|
||||||
|
if (openToCount != 0) {
|
||||||
|
tos = new String[openToCount];
|
||||||
|
for (int j = 0; j < tos.length; ++j) {
|
||||||
|
tos[j] = readModule(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitOpen(open, access, tos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read uses
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
mv.visitUse(readClass(u, buffer));
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read provides
|
||||||
|
u += 2;
|
||||||
|
for (int i = readUnsignedShort(u - 2); i > 0; --i) {
|
||||||
|
String service = readClass(u, buffer);
|
||||||
|
int provideWithCount = readUnsignedShort(u + 2);
|
||||||
|
u += 4;
|
||||||
|
String[] withs = new String[provideWithCount];
|
||||||
|
for (int j = 0; j < withs.length; ++j) {
|
||||||
|
withs[j] = readClass(u, buffer);
|
||||||
|
u += 2;
|
||||||
|
}
|
||||||
|
mv.visitProvide(service, withs);
|
||||||
|
}
|
||||||
|
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a field and makes the given visitor visit it.
|
* Reads a field and makes the given visitor visit it.
|
||||||
*
|
*
|
||||||
|
@ -1082,6 +1215,7 @@ public class ClassReader {
|
||||||
u += 3;
|
u += 3;
|
||||||
break;
|
break;
|
||||||
case ClassWriter.LABELW_INSN:
|
case ClassWriter.LABELW_INSN:
|
||||||
|
case ClassWriter.ASM_LABELW_INSN:
|
||||||
readLabel(offset + readInt(u + 1), labels);
|
readLabel(offset + readInt(u + 1), labels);
|
||||||
u += 5;
|
u += 5;
|
||||||
break;
|
break;
|
||||||
|
@ -1305,7 +1439,8 @@ public class ClassReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((context.flags & EXPAND_ASM_INSNS) != 0) {
|
if ((context.flags & EXPAND_ASM_INSNS) != 0
|
||||||
|
&& (context.flags & EXPAND_FRAMES) != 0) {
|
||||||
// Expanding the ASM pseudo instructions can introduce F_INSERT
|
// Expanding the ASM pseudo instructions can introduce F_INSERT
|
||||||
// frames, even if the method does not currently have any frame.
|
// frames, even if the method does not currently have any frame.
|
||||||
// Also these inserted frames must be computed by simulating the
|
// Also these inserted frames must be computed by simulating the
|
||||||
|
@ -1322,6 +1457,7 @@ public class ClassReader {
|
||||||
|
|
||||||
// visits the instructions
|
// visits the instructions
|
||||||
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
|
int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
|
||||||
|
boolean insertFrame = false;
|
||||||
u = codeStart;
|
u = codeStart;
|
||||||
while (u < codeEnd) {
|
while (u < codeEnd) {
|
||||||
int offset = u - codeStart;
|
int offset = u - codeStart;
|
||||||
|
@ -1354,6 +1490,9 @@ public class ClassReader {
|
||||||
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
|
mv.visitFrame(frame.mode, frame.localDiff, frame.local,
|
||||||
frame.stackCount, frame.stack);
|
frame.stackCount, frame.stack);
|
||||||
}
|
}
|
||||||
|
// if there is already a frame for this offset, there is no
|
||||||
|
// need to insert a new one.
|
||||||
|
insertFrame = false;
|
||||||
}
|
}
|
||||||
if (frameCount > 0) {
|
if (frameCount > 0) {
|
||||||
stackMap = readFrame(stackMap, zip, unzip, frame);
|
stackMap = readFrame(stackMap, zip, unzip, frame);
|
||||||
|
@ -1362,6 +1501,13 @@ public class ClassReader {
|
||||||
frame = null;
|
frame = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// inserts a frame for this offset, if requested by setting
|
||||||
|
// insertFrame to true during the previous iteration. The actual
|
||||||
|
// frame content will be computed in MethodWriter.
|
||||||
|
if (FRAMES && insertFrame) {
|
||||||
|
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
|
||||||
|
insertFrame = false;
|
||||||
|
}
|
||||||
|
|
||||||
// visits the instruction at this offset
|
// visits the instruction at this offset
|
||||||
int opcode = b[u] & 0xFF;
|
int opcode = b[u] & 0xFF;
|
||||||
|
@ -1397,31 +1543,36 @@ public class ClassReader {
|
||||||
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
|
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
|
||||||
Label target = labels[offset + readUnsignedShort(u + 1)];
|
Label target = labels[offset + readUnsignedShort(u + 1)];
|
||||||
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
|
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
|
||||||
// <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
|
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
|
||||||
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
|
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
|
||||||
// and where <l'> designates the instruction just after
|
// and where <L> designates the instruction just after
|
||||||
// the GOTO_W.
|
// the GOTO_W.
|
||||||
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
|
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
|
||||||
mv.visitJumpInsn(opcode + 33, target);
|
mv.visitJumpInsn(opcode + 33, target);
|
||||||
} else {
|
} else {
|
||||||
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
|
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
|
||||||
: opcode ^ 1;
|
: opcode ^ 1;
|
||||||
Label endif = new Label();
|
Label endif = readLabel(offset + 3, labels);
|
||||||
mv.visitJumpInsn(opcode, endif);
|
mv.visitJumpInsn(opcode, endif);
|
||||||
mv.visitJumpInsn(200, target); // GOTO_W
|
mv.visitJumpInsn(200, target); // GOTO_W
|
||||||
mv.visitLabel(endif);
|
// endif designates the instruction just after GOTO_W,
|
||||||
// since we introduced an unconditional jump instruction we
|
// and is visited as part of the next instruction. Since
|
||||||
// also need to insert a stack map frame here, unless there
|
// it is a jump target, we need to insert a frame here.
|
||||||
// is already one. The actual frame content will be computed
|
insertFrame = true;
|
||||||
// in MethodWriter.
|
|
||||||
if (FRAMES && stackMap != 0
|
|
||||||
&& (frame == null || frame.offset != offset + 3)) {
|
|
||||||
mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
u += 3;
|
u += 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ClassWriter.ASM_LABELW_INSN: {
|
||||||
|
// replaces the pseudo GOTO_W instruction with a real one.
|
||||||
|
mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
|
||||||
|
// The instruction just after is a jump target (because pseudo
|
||||||
|
// GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
|
||||||
|
// see MethodWriter), so we need to insert a frame here.
|
||||||
|
insertFrame = true;
|
||||||
|
u += 5;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ClassWriter.WIDE_INSN:
|
case ClassWriter.WIDE_INSN:
|
||||||
opcode = b[u + 1] & 0xFF;
|
opcode = b[u + 1] & 0xFF;
|
||||||
if (opcode == Opcodes.IINC) {
|
if (opcode == Opcodes.IINC) {
|
||||||
|
@ -2516,6 +2667,20 @@ public class ClassReader {
|
||||||
return new String(buf, 0, strLen);
|
return new String(buf, 0, strLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
|
||||||
|
* CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
|
||||||
|
* @param index
|
||||||
|
* @param buf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String readStringish(final int index, final char[] buf) {
|
||||||
|
// computes the start index of the item in b
|
||||||
|
// and reads the CONSTANT_Utf8 item designated by
|
||||||
|
// the first two bytes of this item
|
||||||
|
return readUTF8(items[readUnsignedShort(index)], buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a class constant pool item in {@link #b b}. <i>This method is
|
* Reads a class constant pool item in {@link #b b}. <i>This method is
|
||||||
* intended for {@link Attribute} sub classes, and is normally not needed by
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
|
@ -2530,11 +2695,41 @@ public class ClassReader {
|
||||||
* @return the String corresponding to the specified class item.
|
* @return the String corresponding to the specified class item.
|
||||||
*/
|
*/
|
||||||
public String readClass(final int index, final char[] buf) {
|
public String readClass(final int index, final char[] buf) {
|
||||||
// computes the start index of the CONSTANT_Class item in b
|
return readStringish(index, buf);
|
||||||
// and reads the CONSTANT_Utf8 item designated by
|
}
|
||||||
// the first two bytes of this CONSTANT_Class item
|
|
||||||
String name = readUTF8(items[readUnsignedShort(index)], buf);
|
/**
|
||||||
return (name != null ? name.intern() : null);
|
* Reads a module constant pool item in {@link #b b}. <i>This method is
|
||||||
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
|
* class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* the start index of an unsigned short value in {@link #b b},
|
||||||
|
* whose value is the index of a module constant pool item.
|
||||||
|
* @param buf
|
||||||
|
* buffer to be used to read the item. This buffer must be
|
||||||
|
* sufficiently large. It is not automatically resized.
|
||||||
|
* @return the String corresponding to the specified module item.
|
||||||
|
*/
|
||||||
|
public String readModule(final int index, final char[] buf) {
|
||||||
|
return readStringish(index, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a module constant pool item in {@link #b b}. <i>This method is
|
||||||
|
* intended for {@link Attribute} sub classes, and is normally not needed by
|
||||||
|
* class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* the start index of an unsigned short value in {@link #b b},
|
||||||
|
* whose value is the index of a module constant pool item.
|
||||||
|
* @param buf
|
||||||
|
* buffer to be used to read the item. This buffer must be
|
||||||
|
* sufficiently large. It is not automatically resized.
|
||||||
|
* @return the String corresponding to the specified module item.
|
||||||
|
*/
|
||||||
|
public String readPackage(final int index, final char[] buf) {
|
||||||
|
return readStringish(index, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,7 +32,7 @@ package org.springframework.asm;
|
||||||
/**
|
/**
|
||||||
* A visitor to visit a Java class. The methods of this class must be called in
|
* A visitor to visit a Java class. The methods of this class must be called in
|
||||||
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
||||||
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
||||||
* <tt>visitEnd</tt>.
|
* <tt>visitEnd</tt>.
|
||||||
|
@ -43,7 +43,7 @@ public abstract class ClassVisitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ public abstract class ClassVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public ClassVisitor(final int api) {
|
public ClassVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
|
@ -69,13 +69,13 @@ public abstract class ClassVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param cv
|
* @param cv
|
||||||
* the class visitor to which this visitor must delegate method
|
* the class visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public ClassVisitor(final int api, final ClassVisitor cv) {
|
public ClassVisitor(final int api, final ClassVisitor cv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
this.api = api;
|
this.api = api;
|
||||||
|
@ -131,6 +131,28 @@ public abstract class ClassVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the module corresponding to the class.
|
||||||
|
* @param name
|
||||||
|
* module name
|
||||||
|
* @param access
|
||||||
|
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
|
||||||
|
* and {@code ACC_MANDATED}.
|
||||||
|
* @param version
|
||||||
|
* module version or null.
|
||||||
|
* @return a visitor to visit the module values, or <tt>null</tt> if
|
||||||
|
* this visitor is not interested in visiting this module.
|
||||||
|
*/
|
||||||
|
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||||
|
if (api < Opcodes.ASM6) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
if (cv != null) {
|
||||||
|
return cv.visitModule(name, access, version);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits the enclosing class of the class. This method must be called only
|
* Visits the enclosing class of the class. This method must be called only
|
||||||
* if the class has an enclosing class.
|
* if the class has an enclosing class.
|
||||||
|
|
|
@ -173,6 +173,11 @@ public class ClassWriter extends ClassVisitor {
|
||||||
*/
|
*/
|
||||||
static final int ASM_LABEL_INSN = 18;
|
static final int ASM_LABEL_INSN = 18;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the ASM pseudo instructions with a 4 bytes offset label.
|
||||||
|
*/
|
||||||
|
static final int ASM_LABELW_INSN = 19;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a frame inserted between already existing frames. This kind of
|
* Represents a frame inserted between already existing frames. This kind of
|
||||||
* frame can only be used if the frame content can be computed from the
|
* frame can only be used if the frame content can be computed from the
|
||||||
|
@ -258,10 +263,20 @@ public class ClassWriter extends ClassVisitor {
|
||||||
*/
|
*/
|
||||||
static final int INDY = 18;
|
static final int INDY = 18;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of CONSTANT_Module constant pool items.
|
||||||
|
*/
|
||||||
|
static final int MODULE = 19;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of CONSTANT_Package constant pool items.
|
||||||
|
*/
|
||||||
|
static final int PACKAGE = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base value for all CONSTANT_MethodHandle constant pool items.
|
* The base value for all CONSTANT_MethodHandle constant pool items.
|
||||||
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
|
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
|
||||||
* different items.
|
* different items (from 21 to 29).
|
||||||
*/
|
*/
|
||||||
static final int HANDLE_BASE = 20;
|
static final int HANDLE_BASE = 20;
|
||||||
|
|
||||||
|
@ -410,6 +425,11 @@ public class ClassWriter extends ClassVisitor {
|
||||||
*/
|
*/
|
||||||
private ByteVector sourceDebug;
|
private ByteVector sourceDebug;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module attribute of this class.
|
||||||
|
*/
|
||||||
|
private ModuleWriter moduleWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constant pool item that contains the name of the enclosing class of
|
* The constant pool item that contains the name of the enclosing class of
|
||||||
* this class.
|
* this class.
|
||||||
|
@ -523,11 +543,11 @@ public class ClassWriter extends ClassVisitor {
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
int i;
|
int i;
|
||||||
byte[] b = new byte[220];
|
byte[] b = new byte[221];
|
||||||
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
|
String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
|
||||||
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
+ "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||||
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
|
+ "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
|
||||||
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSS";
|
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKSSSSSSSSSSSSSSSSSST";
|
||||||
for (i = 0; i < b.length; ++i) {
|
for (i = 0; i < b.length; ++i) {
|
||||||
b[i] = (byte) (s.charAt(i) - 'A');
|
b[i] = (byte) (s.charAt(i) - 'A');
|
||||||
}
|
}
|
||||||
|
@ -583,6 +603,7 @@ public class ClassWriter extends ClassVisitor {
|
||||||
// for (i = 202; i < 220; ++i) {
|
// for (i = 202; i < 220; ++i) {
|
||||||
// b[i] = ASM_LABEL_INSN;
|
// b[i] = ASM_LABEL_INSN;
|
||||||
// }
|
// }
|
||||||
|
// b[220] = ASM_LABELW_INSN;
|
||||||
//
|
//
|
||||||
// // LDC(_W) instructions
|
// // LDC(_W) instructions
|
||||||
// b[Constants.LDC] = LDC_INSN;
|
// b[Constants.LDC] = LDC_INSN;
|
||||||
|
@ -615,7 +636,7 @@ public class ClassWriter extends ClassVisitor {
|
||||||
* {@link #COMPUTE_FRAMES}.
|
* {@link #COMPUTE_FRAMES}.
|
||||||
*/
|
*/
|
||||||
public ClassWriter(final int flags) {
|
public ClassWriter(final int flags) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
index = 1;
|
index = 1;
|
||||||
pool = new ByteVector();
|
pool = new ByteVector();
|
||||||
items = new Item[256];
|
items = new Item[256];
|
||||||
|
@ -703,6 +724,14 @@ public class ClassWriter extends ClassVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ModuleVisitor visitModule(final String name,
|
||||||
|
final int access, final String version) {
|
||||||
|
return moduleWriter = new ModuleWriter(this,
|
||||||
|
newModule(name), access,
|
||||||
|
version == null ? 0 : newUTF8(version));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void visitOuterClass(final String owner, final String name,
|
public final void visitOuterClass(final String owner, final String name,
|
||||||
final String desc) {
|
final String desc) {
|
||||||
|
@ -777,7 +806,7 @@ public class ClassWriter extends ClassVisitor {
|
||||||
// and equality tests). If so we store the index of this inner class
|
// and equality tests). If so we store the index of this inner class
|
||||||
// entry (plus one) in intVal. This hack allows duplicate detection in
|
// entry (plus one) in intVal. This hack allows duplicate detection in
|
||||||
// O(1) time.
|
// O(1) time.
|
||||||
Item nameItem = newClassItem(name);
|
Item nameItem = newStringishItem(CLASS, name);
|
||||||
if (nameItem.intVal == 0) {
|
if (nameItem.intVal == 0) {
|
||||||
++innerClassesCount;
|
++innerClassesCount;
|
||||||
innerClasses.putShort(nameItem.index);
|
innerClasses.putShort(nameItem.index);
|
||||||
|
@ -904,6 +933,11 @@ public class ClassWriter extends ClassVisitor {
|
||||||
size += 8 + itanns.getSize();
|
size += 8 + itanns.getSize();
|
||||||
newUTF8("RuntimeInvisibleTypeAnnotations");
|
newUTF8("RuntimeInvisibleTypeAnnotations");
|
||||||
}
|
}
|
||||||
|
if (moduleWriter != null) {
|
||||||
|
attributeCount += 1 + moduleWriter.attributeCount;
|
||||||
|
size += 6 + moduleWriter.size + moduleWriter.attributesSize;
|
||||||
|
newUTF8("Module");
|
||||||
|
}
|
||||||
if (attrs != null) {
|
if (attrs != null) {
|
||||||
attributeCount += attrs.getCount();
|
attributeCount += attrs.getCount();
|
||||||
size += attrs.getSize(this, null, 0, -1, -1);
|
size += attrs.getSize(this, null, 0, -1, -1);
|
||||||
|
@ -951,6 +985,11 @@ public class ClassWriter extends ClassVisitor {
|
||||||
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
|
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
|
||||||
out.putByteArray(sourceDebug.data, 0, len);
|
out.putByteArray(sourceDebug.data, 0, len);
|
||||||
}
|
}
|
||||||
|
if (moduleWriter != null) {
|
||||||
|
out.putShort(newUTF8("Module"));
|
||||||
|
moduleWriter.put(out);
|
||||||
|
moduleWriter.putAttributes(out);
|
||||||
|
}
|
||||||
if (enclosingMethodOwner != 0) {
|
if (enclosingMethodOwner != 0) {
|
||||||
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
|
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
|
||||||
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
|
out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
|
||||||
|
@ -989,18 +1028,26 @@ public class ClassWriter extends ClassVisitor {
|
||||||
attrs.put(this, null, 0, -1, -1, out);
|
attrs.put(this, null, 0, -1, -1, out);
|
||||||
}
|
}
|
||||||
if (hasAsmInsns) {
|
if (hasAsmInsns) {
|
||||||
|
boolean hasFrames = false;
|
||||||
|
mb = firstMethod;
|
||||||
|
while (mb != null) {
|
||||||
|
hasFrames |= mb.frameCount > 0;
|
||||||
|
mb = (MethodWriter) mb.mv;
|
||||||
|
}
|
||||||
anns = null;
|
anns = null;
|
||||||
ianns = null;
|
ianns = null;
|
||||||
attrs = null;
|
attrs = null;
|
||||||
|
moduleWriter = null;
|
||||||
innerClassesCount = 0;
|
innerClassesCount = 0;
|
||||||
innerClasses = null;
|
innerClasses = null;
|
||||||
firstField = null;
|
firstField = null;
|
||||||
lastField = null;
|
lastField = null;
|
||||||
firstMethod = null;
|
firstMethod = null;
|
||||||
lastMethod = null;
|
lastMethod = null;
|
||||||
compute = MethodWriter.INSERTED_FRAMES;
|
compute = hasFrames ? MethodWriter.INSERTED_FRAMES : 0;
|
||||||
hasAsmInsns = false;
|
hasAsmInsns = false;
|
||||||
new ClassReader(out.data).accept(this, ClassReader.EXPAND_FRAMES
|
new ClassReader(out.data).accept(this,
|
||||||
|
(hasFrames ? ClassReader.EXPAND_FRAMES : 0)
|
||||||
| ClassReader.EXPAND_ASM_INSNS);
|
| ClassReader.EXPAND_ASM_INSNS);
|
||||||
return toByteArray();
|
return toByteArray();
|
||||||
}
|
}
|
||||||
|
@ -1048,16 +1095,16 @@ public class ClassWriter extends ClassVisitor {
|
||||||
double val = ((Double) cst).doubleValue();
|
double val = ((Double) cst).doubleValue();
|
||||||
return newDouble(val);
|
return newDouble(val);
|
||||||
} else if (cst instanceof String) {
|
} else if (cst instanceof String) {
|
||||||
return newString((String) cst);
|
return newStringishItem(STR, (String) cst);
|
||||||
} else if (cst instanceof Type) {
|
} else if (cst instanceof Type) {
|
||||||
Type t = (Type) cst;
|
Type t = (Type) cst;
|
||||||
int s = t.getSort();
|
int s = t.getSort();
|
||||||
if (s == Type.OBJECT) {
|
if (s == Type.OBJECT) {
|
||||||
return newClassItem(t.getInternalName());
|
return newStringishItem(CLASS, t.getInternalName());
|
||||||
} else if (s == Type.METHOD) {
|
} else if (s == Type.METHOD) {
|
||||||
return newMethodTypeItem(t.getDescriptor());
|
return newStringishItem(MTYPE, t.getDescriptor());
|
||||||
} else { // s == primitive type or array
|
} else { // s == primitive type or array
|
||||||
return newClassItem(t.getDescriptor());
|
return newStringishItem(CLASS, t.getDescriptor());
|
||||||
}
|
}
|
||||||
} else if (cst instanceof Handle) {
|
} else if (cst instanceof Handle) {
|
||||||
Handle h = (Handle) cst;
|
Handle h = (Handle) cst;
|
||||||
|
@ -1106,20 +1153,21 @@ public class ClassWriter extends ClassVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a class reference to the constant pool of the class being build.
|
* Adds a string reference, a class reference, a method type, a module
|
||||||
|
* or a package to the constant pool of the class being build.
|
||||||
* Does nothing if the constant pool already contains a similar item.
|
* Does nothing if the constant pool already contains a similar item.
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
*
|
||||||
|
* @param type
|
||||||
|
* a type among STR, CLASS, MTYPE, MODULE or PACKAGE
|
||||||
* @param value
|
* @param value
|
||||||
* the internal name of the class.
|
* string value of the reference.
|
||||||
* @return a new or already existing class reference item.
|
* @return a new or already existing reference item.
|
||||||
*/
|
*/
|
||||||
Item newClassItem(final String value) {
|
Item newStringishItem(final int type, final String value) {
|
||||||
key2.set(CLASS, value, null, null);
|
key2.set(type, value, null, null);
|
||||||
Item result = get(key2);
|
Item result = get(key2);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
pool.put12(CLASS, newUTF8(value));
|
pool.put12(type, newUTF8(value));
|
||||||
result = new Item(index++, key2);
|
result = new Item(index++, key2);
|
||||||
put(result);
|
put(result);
|
||||||
}
|
}
|
||||||
|
@ -1137,28 +1185,7 @@ public class ClassWriter extends ClassVisitor {
|
||||||
* @return the index of a new or already existing class reference item.
|
* @return the index of a new or already existing class reference item.
|
||||||
*/
|
*/
|
||||||
public int newClass(final String value) {
|
public int newClass(final String value) {
|
||||||
return newClassItem(value).index;
|
return newStringishItem(CLASS, value).index;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a method type reference to the constant pool of the class being
|
|
||||||
* build. Does nothing if the constant pool already contains a similar item.
|
|
||||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
|
||||||
* normally not needed by class generators or adapters.</i>
|
|
||||||
*
|
|
||||||
* @param methodDesc
|
|
||||||
* method descriptor of the method type.
|
|
||||||
* @return a new or already existing method type reference item.
|
|
||||||
*/
|
|
||||||
Item newMethodTypeItem(final String methodDesc) {
|
|
||||||
key2.set(MTYPE, methodDesc, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(MTYPE, newUTF8(methodDesc));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1173,7 +1200,37 @@ public class ClassWriter extends ClassVisitor {
|
||||||
* item.
|
* item.
|
||||||
*/
|
*/
|
||||||
public int newMethodType(final String methodDesc) {
|
public int newMethodType(final String methodDesc) {
|
||||||
return newMethodTypeItem(methodDesc).index;
|
return newStringishItem(MTYPE, methodDesc).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a module reference to the constant pool of the class being
|
||||||
|
* build. Does nothing if the constant pool already contains a similar item.
|
||||||
|
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||||
|
* normally not needed by class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* name of the module.
|
||||||
|
* @return the index of a new or already existing module reference
|
||||||
|
* item.
|
||||||
|
*/
|
||||||
|
public int newModule(final String moduleName) {
|
||||||
|
return newStringishItem(MODULE, moduleName).index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a package reference to the constant pool of the class being
|
||||||
|
* build. Does nothing if the constant pool already contains a similar item.
|
||||||
|
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||||
|
* normally not needed by class generators or adapters.</i>
|
||||||
|
*
|
||||||
|
* @param packageName
|
||||||
|
* name of the package in its internal form.
|
||||||
|
* @return the index of a new or already existing module reference
|
||||||
|
* item.
|
||||||
|
*/
|
||||||
|
public int newPackage(final String packageName) {
|
||||||
|
return newStringishItem(PACKAGE, packageName).index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1554,25 +1611,6 @@ public class ClassWriter extends ClassVisitor {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a string to the constant pool of the class being build. Does nothing
|
|
||||||
* if the constant pool already contains a similar item.
|
|
||||||
*
|
|
||||||
* @param value
|
|
||||||
* the String value.
|
|
||||||
* @return a new or already existing string item.
|
|
||||||
*/
|
|
||||||
private Item newString(final String value) {
|
|
||||||
key2.set(STR, value, null, null);
|
|
||||||
Item result = get(key2);
|
|
||||||
if (result == null) {
|
|
||||||
pool.put12(STR, newUTF8(value));
|
|
||||||
result = new Item(index++, key2);
|
|
||||||
put(result);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a name and type to the constant pool of the class being build. Does
|
* Adds a name and type to the constant pool of the class being build. Does
|
||||||
* nothing if the constant pool already contains a similar item. <i>This
|
* nothing if the constant pool already contains a similar item. <i>This
|
||||||
|
|
|
@ -40,7 +40,7 @@ public abstract class FieldVisitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public abstract class FieldVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public FieldVisitor(final int api) {
|
public FieldVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
|
@ -66,13 +66,13 @@ public abstract class FieldVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param fv
|
* @param fv
|
||||||
* the field visitor to which this visitor must delegate method
|
* the field visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public FieldVisitor(final int api, final FieldVisitor fv) {
|
public FieldVisitor(final int api, final FieldVisitor fv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
this.api = api;
|
this.api = api;
|
||||||
|
|
|
@ -118,7 +118,7 @@ final class FieldWriter extends FieldVisitor {
|
||||||
*/
|
*/
|
||||||
FieldWriter(final ClassWriter cw, final int access, final String name,
|
FieldWriter(final ClassWriter cw, final int access, final String name,
|
||||||
final String desc, final String signature, final Object value) {
|
final String desc, final String signature, final Object value) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
if (cw.firstField == null) {
|
if (cw.firstField == null) {
|
||||||
cw.firstField = this;
|
cw.firstField = this;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -51,6 +51,7 @@ final class Item {
|
||||||
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
|
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
|
||||||
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
|
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
|
||||||
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
|
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
|
||||||
|
* {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
|
||||||
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
|
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
|
||||||
*
|
*
|
||||||
* MethodHandle constant 9 variations are stored using a range of 9 values
|
* MethodHandle constant 9 variations are stored using a range of 9 values
|
||||||
|
@ -214,6 +215,8 @@ final class Item {
|
||||||
case ClassWriter.UTF8:
|
case ClassWriter.UTF8:
|
||||||
case ClassWriter.STR:
|
case ClassWriter.STR:
|
||||||
case ClassWriter.MTYPE:
|
case ClassWriter.MTYPE:
|
||||||
|
case ClassWriter.MODULE:
|
||||||
|
case ClassWriter.PACKAGE:
|
||||||
case ClassWriter.TYPE_NORMAL:
|
case ClassWriter.TYPE_NORMAL:
|
||||||
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
|
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
|
||||||
return;
|
return;
|
||||||
|
@ -282,6 +285,8 @@ final class Item {
|
||||||
case ClassWriter.UTF8:
|
case ClassWriter.UTF8:
|
||||||
case ClassWriter.STR:
|
case ClassWriter.STR:
|
||||||
case ClassWriter.CLASS:
|
case ClassWriter.CLASS:
|
||||||
|
case ClassWriter.MODULE:
|
||||||
|
case ClassWriter.PACKAGE:
|
||||||
case ClassWriter.MTYPE:
|
case ClassWriter.MTYPE:
|
||||||
case ClassWriter.TYPE_NORMAL:
|
case ClassWriter.TYPE_NORMAL:
|
||||||
return i.strVal1.equals(strVal1);
|
return i.strVal1.equals(strVal1);
|
||||||
|
|
|
@ -57,7 +57,7 @@ public abstract class MethodVisitor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM API version implemented by this visitor. The value of this field
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
* must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
protected final int api;
|
protected final int api;
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ public abstract class MethodVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public MethodVisitor(final int api) {
|
public MethodVisitor(final int api) {
|
||||||
this(api, null);
|
this(api, null);
|
||||||
|
@ -83,13 +83,13 @@ public abstract class MethodVisitor {
|
||||||
*
|
*
|
||||||
* @param api
|
* @param api
|
||||||
* the ASM API version implemented by this visitor. Must be one
|
* the ASM API version implemented by this visitor. Must be one
|
||||||
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
|
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||||
* @param mv
|
* @param mv
|
||||||
* the method visitor to which this visitor must delegate method
|
* the method visitor to which this visitor must delegate method
|
||||||
* calls. May be null.
|
* calls. May be null.
|
||||||
*/
|
*/
|
||||||
public MethodVisitor(final int api, final MethodVisitor mv) {
|
public MethodVisitor(final int api, final MethodVisitor mv) {
|
||||||
if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
|
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
this.api = api;
|
this.api = api;
|
||||||
|
|
|
@ -260,7 +260,7 @@ class MethodWriter extends MethodVisitor {
|
||||||
/**
|
/**
|
||||||
* Number of stack map frames in the StackMapTable attribute.
|
* Number of stack map frames in the StackMapTable attribute.
|
||||||
*/
|
*/
|
||||||
private int frameCount;
|
int frameCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The StackMapTable attribute.
|
* The StackMapTable attribute.
|
||||||
|
@ -456,7 +456,7 @@ class MethodWriter extends MethodVisitor {
|
||||||
MethodWriter(final ClassWriter cw, final int access, final String name,
|
MethodWriter(final ClassWriter cw, final int access, final String name,
|
||||||
final String desc, final String signature,
|
final String desc, final String signature,
|
||||||
final String[] exceptions, final int compute) {
|
final String[] exceptions, final int compute) {
|
||||||
super(Opcodes.ASM5);
|
super(Opcodes.ASM6);
|
||||||
if (cw.firstMethod == null) {
|
if (cw.firstMethod == null) {
|
||||||
cw.firstMethod = this;
|
cw.firstMethod = this;
|
||||||
} else {
|
} else {
|
||||||
|
@ -848,7 +848,7 @@ class MethodWriter extends MethodVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visitTypeInsn(final int opcode, final String type) {
|
public void visitTypeInsn(final int opcode, final String type) {
|
||||||
lastCodeOffset = code.length;
|
lastCodeOffset = code.length;
|
||||||
Item i = cw.newClassItem(type);
|
Item i = cw.newStringishItem(ClassWriter.CLASS, type);
|
||||||
// Label currentBlock = this.currentBlock;
|
// Label currentBlock = this.currentBlock;
|
||||||
if (currentBlock != null) {
|
if (currentBlock != null) {
|
||||||
if (compute == FRAMES || compute == INSERTED_FRAMES) {
|
if (compute == FRAMES || compute == INSERTED_FRAMES) {
|
||||||
|
@ -1050,8 +1050,8 @@ class MethodWriter extends MethodVisitor {
|
||||||
/*
|
/*
|
||||||
* case of a backward jump with an offset < -32768. In this case we
|
* case of a backward jump with an offset < -32768. In this case we
|
||||||
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
|
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
|
||||||
* <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
|
* <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is the
|
||||||
* "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
|
* "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <L>
|
||||||
* designates the instruction just after the GOTO_W.
|
* designates the instruction just after the GOTO_W.
|
||||||
*/
|
*/
|
||||||
if (opcode == Opcodes.GOTO) {
|
if (opcode == Opcodes.GOTO) {
|
||||||
|
@ -1067,7 +1067,11 @@ class MethodWriter extends MethodVisitor {
|
||||||
code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
|
code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
|
||||||
: opcode ^ 1);
|
: opcode ^ 1);
|
||||||
code.putShort(8); // jump offset
|
code.putShort(8); // jump offset
|
||||||
code.putByte(200); // GOTO_W
|
// ASM pseudo GOTO_W insn, see ClassReader. We don't use a real
|
||||||
|
// GOTO_W because we might need to insert a frame just after (as
|
||||||
|
// the target of the IFNOTxxx jump instruction).
|
||||||
|
code.putByte(220);
|
||||||
|
cw.hasAsmInsns = true;
|
||||||
}
|
}
|
||||||
label.put(this, code, code.length - 1, true);
|
label.put(this, code, code.length - 1, true);
|
||||||
} else if (isWide) {
|
} else if (isWide) {
|
||||||
|
@ -1291,7 +1295,7 @@ class MethodWriter extends MethodVisitor {
|
||||||
@Override
|
@Override
|
||||||
public void visitMultiANewArrayInsn(final String desc, final int dims) {
|
public void visitMultiANewArrayInsn(final String desc, final int dims) {
|
||||||
lastCodeOffset = code.length;
|
lastCodeOffset = code.length;
|
||||||
Item i = cw.newClassItem(desc);
|
Item i = cw.newStringishItem(ClassWriter.CLASS, desc);
|
||||||
// Label currentBlock = this.currentBlock;
|
// Label currentBlock = this.currentBlock;
|
||||||
if (currentBlock != null) {
|
if (currentBlock != null) {
|
||||||
if (compute == FRAMES || compute == INSERTED_FRAMES) {
|
if (compute == FRAMES || compute == INSERTED_FRAMES) {
|
||||||
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
/***
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.asm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A visitor to visit a Java module. The methods of this class must be called in
|
||||||
|
* the following order: <tt>visitVersion</tt> | <tt>visitMainClass</tt> |
|
||||||
|
* <tt>visitTargetPlatform</tt> | ( <tt>visitConcealedPackage</tt> | <tt>visitRequire</tt> |
|
||||||
|
* <tt>visitExport</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||||
|
*
|
||||||
|
* @author Remi Forax
|
||||||
|
*/
|
||||||
|
public abstract class ModuleVisitor {
|
||||||
|
/**
|
||||||
|
* The ASM API version implemented by this visitor. The value of this field
|
||||||
|
* must be {@link Opcodes#ASM6}.
|
||||||
|
*/
|
||||||
|
protected final int api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module visitor to which this visitor must delegate method calls. May
|
||||||
|
* be null.
|
||||||
|
*/
|
||||||
|
protected ModuleVisitor mv;
|
||||||
|
|
||||||
|
|
||||||
|
public ModuleVisitor(final int api) {
|
||||||
|
this(api, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@link MethodVisitor}.
|
||||||
|
*
|
||||||
|
* @param api
|
||||||
|
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||||
|
* @param mv
|
||||||
|
* the method visitor to which this visitor must delegate method
|
||||||
|
* calls. May be null.
|
||||||
|
*/
|
||||||
|
public ModuleVisitor(final int api, final ModuleVisitor mv) {
|
||||||
|
if (api != Opcodes.ASM6) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
this.api = api;
|
||||||
|
this.mv = mv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the main class of the current module.
|
||||||
|
*
|
||||||
|
* @param mainClass the main class of the current module.
|
||||||
|
*/
|
||||||
|
public void visitMainClass(String mainClass) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitMainClass(mainClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a concealed package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze name of a concealed package
|
||||||
|
*/
|
||||||
|
public void visitPackage(String packaze) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitPackage(packaze);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits a dependence of the current module.
|
||||||
|
*
|
||||||
|
* @param module the module name of the dependence
|
||||||
|
* @param access the access flag of the dependence among
|
||||||
|
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
|
||||||
|
* and ACC_MANDATED.
|
||||||
|
* @param version the module version at compile time or null.
|
||||||
|
*/
|
||||||
|
public void visitRequire(String module, int access, String version) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitRequire(module, access, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an exported package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze the name of the exported package.
|
||||||
|
* @param access the access flag of the exported package,
|
||||||
|
* valid values are among {@code ACC_SYNTHETIC} and
|
||||||
|
* {@code ACC_MANDATED}.
|
||||||
|
* @param modules names of the modules that can access to
|
||||||
|
* the public classes of the exported package or
|
||||||
|
* <tt>null</tt>.
|
||||||
|
*/
|
||||||
|
public void visitExport(String packaze, int access, String... modules) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitExport(packaze, access, modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an open package of the current module.
|
||||||
|
*
|
||||||
|
* @param packaze the name of the opened package.
|
||||||
|
* @param access the access flag of the opened package,
|
||||||
|
* valid values are among {@code ACC_SYNTHETIC} and
|
||||||
|
* {@code ACC_MANDATED}.
|
||||||
|
* @param modules names of the modules that can use deep
|
||||||
|
* reflection to the classes of the open package or
|
||||||
|
* <tt>null</tt>.
|
||||||
|
*/
|
||||||
|
public void visitOpen(String packaze, int access, String... modules) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitOpen(packaze, access, modules);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit a service used by the current module.
|
||||||
|
* The name must be the name of an interface or an
|
||||||
|
* abstract class.
|
||||||
|
*
|
||||||
|
* @param service the internal name of the service.
|
||||||
|
*/
|
||||||
|
public void visitUse(String service) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitUse(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit an implementation of a service.
|
||||||
|
*
|
||||||
|
* @param service the internal name of the service
|
||||||
|
* @param providers the internal names of the implementations
|
||||||
|
* of the service (there is at least one provider).
|
||||||
|
*/
|
||||||
|
public void visitProvide(String service, String... providers) {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitProvide(service, providers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void visitEnd() {
|
||||||
|
if (mv != null) {
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
/***
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2011 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.asm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Remi Forax
|
||||||
|
*/
|
||||||
|
final class ModuleWriter extends ModuleVisitor {
|
||||||
|
/**
|
||||||
|
* The class writer to which this Module attribute must be added.
|
||||||
|
*/
|
||||||
|
private final ClassWriter cw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* size in byte of the Module attribute.
|
||||||
|
*/
|
||||||
|
int size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of attributes associated with the current module
|
||||||
|
* (Version, ConcealPackages, etc)
|
||||||
|
*/
|
||||||
|
int attributeCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size in bytes of the attributes associated with the current module
|
||||||
|
*/
|
||||||
|
int attributesSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module name index in the constant pool
|
||||||
|
*/
|
||||||
|
private final int name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module access flags
|
||||||
|
*/
|
||||||
|
private final int access;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module version index in the constant pool or 0
|
||||||
|
*/
|
||||||
|
private final int version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* module main class index in the constant pool or 0
|
||||||
|
*/
|
||||||
|
private int mainClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of packages
|
||||||
|
*/
|
||||||
|
private int packageCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packages in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in packageCount
|
||||||
|
*/
|
||||||
|
private ByteVector packages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of requires items
|
||||||
|
*/
|
||||||
|
private int requireCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requires items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in requireCount
|
||||||
|
*/
|
||||||
|
private ByteVector requires;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of exports items
|
||||||
|
*/
|
||||||
|
private int exportCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The exports items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in exportCount
|
||||||
|
*/
|
||||||
|
private ByteVector exports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of opens items
|
||||||
|
*/
|
||||||
|
private int openCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The opens items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in openCount
|
||||||
|
*/
|
||||||
|
private ByteVector opens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of uses items
|
||||||
|
*/
|
||||||
|
private int useCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uses items in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in useCount
|
||||||
|
*/
|
||||||
|
private ByteVector uses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* number of provides items
|
||||||
|
*/
|
||||||
|
private int provideCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The uses provides in bytecode form. This byte vector only contains
|
||||||
|
* the items themselves, the number of items is store in provideCount
|
||||||
|
*/
|
||||||
|
private ByteVector provides;
|
||||||
|
|
||||||
|
ModuleWriter(final ClassWriter cw, final int name,
|
||||||
|
final int access, final int version) {
|
||||||
|
super(Opcodes.ASM6);
|
||||||
|
this.cw = cw;
|
||||||
|
this.size = 16; // name + access + version + 5 counts
|
||||||
|
this.name = name;
|
||||||
|
this.access = access;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMainClass(String mainClass) {
|
||||||
|
if (this.mainClass == 0) { // protect against several calls to visitMainClass
|
||||||
|
cw.newUTF8("ModuleMainClass");
|
||||||
|
attributeCount++;
|
||||||
|
attributesSize += 8;
|
||||||
|
}
|
||||||
|
this.mainClass = cw.newClass(mainClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPackage(String packaze) {
|
||||||
|
if (packages == null) {
|
||||||
|
// protect against several calls to visitPackage
|
||||||
|
cw.newUTF8("ModulePackages");
|
||||||
|
packages = new ByteVector();
|
||||||
|
attributeCount++;
|
||||||
|
attributesSize += 8;
|
||||||
|
}
|
||||||
|
packages.putShort(cw.newPackage(packaze));
|
||||||
|
packageCount++;
|
||||||
|
attributesSize += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitRequire(String module, int access, String version) {
|
||||||
|
if (requires == null) {
|
||||||
|
requires = new ByteVector();
|
||||||
|
}
|
||||||
|
requires.putShort(cw.newModule(module))
|
||||||
|
.putShort(access)
|
||||||
|
.putShort(version == null? 0: cw.newUTF8(version));
|
||||||
|
requireCount++;
|
||||||
|
size += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitExport(String packaze, int access, String... modules) {
|
||||||
|
if (exports == null) {
|
||||||
|
exports = new ByteVector();
|
||||||
|
}
|
||||||
|
exports.putShort(cw.newPackage(packaze)).putShort(access);
|
||||||
|
if (modules == null) {
|
||||||
|
exports.putShort(0);
|
||||||
|
size += 6;
|
||||||
|
} else {
|
||||||
|
exports.putShort(modules.length);
|
||||||
|
for(String module: modules) {
|
||||||
|
exports.putShort(cw.newModule(module));
|
||||||
|
}
|
||||||
|
size += 6 + 2 * modules.length;
|
||||||
|
}
|
||||||
|
exportCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitOpen(String packaze, int access, String... modules) {
|
||||||
|
if (opens == null) {
|
||||||
|
opens = new ByteVector();
|
||||||
|
}
|
||||||
|
opens.putShort(cw.newPackage(packaze)).putShort(access);
|
||||||
|
if (modules == null) {
|
||||||
|
opens.putShort(0);
|
||||||
|
size += 6;
|
||||||
|
} else {
|
||||||
|
opens.putShort(modules.length);
|
||||||
|
for(String module: modules) {
|
||||||
|
opens.putShort(cw.newModule(module));
|
||||||
|
}
|
||||||
|
size += 6 + 2 * modules.length;
|
||||||
|
}
|
||||||
|
openCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitUse(String service) {
|
||||||
|
if (uses == null) {
|
||||||
|
uses = new ByteVector();
|
||||||
|
}
|
||||||
|
uses.putShort(cw.newClass(service));
|
||||||
|
useCount++;
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitProvide(String service, String... providers) {
|
||||||
|
if (provides == null) {
|
||||||
|
provides = new ByteVector();
|
||||||
|
}
|
||||||
|
provides.putShort(cw.newClass(service));
|
||||||
|
provides.putShort(providers.length);
|
||||||
|
for(String provider: providers) {
|
||||||
|
provides.putShort(cw.newClass(provider));
|
||||||
|
}
|
||||||
|
provideCount++;
|
||||||
|
size += 4 + 2 * providers.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEnd() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void putAttributes(ByteVector out) {
|
||||||
|
if (mainClass != 0) {
|
||||||
|
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
|
||||||
|
}
|
||||||
|
if (packages != null) {
|
||||||
|
out.putShort(cw.newUTF8("ModulePackages"))
|
||||||
|
.putInt(2 + 2 * packageCount)
|
||||||
|
.putShort(packageCount)
|
||||||
|
.putByteArray(packages.data, 0, packages.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(ByteVector out) {
|
||||||
|
out.putInt(size);
|
||||||
|
out.putShort(name).putShort(access).putShort(version);
|
||||||
|
out.putShort(requireCount);
|
||||||
|
if (requires != null) {
|
||||||
|
out.putByteArray(requires.data, 0, requires.length);
|
||||||
|
}
|
||||||
|
out.putShort(exportCount);
|
||||||
|
if (exports != null) {
|
||||||
|
out.putByteArray(exports.data, 0, exports.length);
|
||||||
|
}
|
||||||
|
out.putShort(openCount);
|
||||||
|
if (opens != null) {
|
||||||
|
out.putByteArray(opens.data, 0, opens.length);
|
||||||
|
}
|
||||||
|
out.putShort(useCount);
|
||||||
|
if (uses != null) {
|
||||||
|
out.putByteArray(uses.data, 0, uses.length);
|
||||||
|
}
|
||||||
|
out.putShort(provideCount);
|
||||||
|
if (provides != null) {
|
||||||
|
out.putByteArray(provides.data, 0, provides.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ public interface Opcodes {
|
||||||
|
|
||||||
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
||||||
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
||||||
|
int ASM6 = 6 << 16 | 0 << 8 | 0;
|
||||||
|
|
||||||
// versions
|
// versions
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ public interface Opcodes {
|
||||||
int V1_6 = 0 << 16 | 50;
|
int V1_6 = 0 << 16 | 50;
|
||||||
int V1_7 = 0 << 16 | 51;
|
int V1_7 = 0 << 16 | 51;
|
||||||
int V1_8 = 0 << 16 | 52;
|
int V1_8 = 0 << 16 | 52;
|
||||||
|
int V1_9 = 0 << 16 | 53;
|
||||||
|
|
||||||
// access flags
|
// access flags
|
||||||
|
|
||||||
|
@ -68,18 +70,23 @@ public interface Opcodes {
|
||||||
int ACC_FINAL = 0x0010; // class, field, method, parameter
|
int ACC_FINAL = 0x0010; // class, field, method, parameter
|
||||||
int ACC_SUPER = 0x0020; // class
|
int ACC_SUPER = 0x0020; // class
|
||||||
int ACC_SYNCHRONIZED = 0x0020; // method
|
int ACC_SYNCHRONIZED = 0x0020; // method
|
||||||
|
int ACC_OPEN = 0x0020; // module
|
||||||
|
int ACC_TRANSITIVE = 0x0020; // module requires
|
||||||
int ACC_VOLATILE = 0x0040; // field
|
int ACC_VOLATILE = 0x0040; // field
|
||||||
int ACC_BRIDGE = 0x0040; // method
|
int ACC_BRIDGE = 0x0040; // method
|
||||||
|
int ACC_STATIC_PHASE = 0x0040; // module requires
|
||||||
int ACC_VARARGS = 0x0080; // method
|
int ACC_VARARGS = 0x0080; // method
|
||||||
int ACC_TRANSIENT = 0x0080; // field
|
int ACC_TRANSIENT = 0x0080; // field
|
||||||
int ACC_NATIVE = 0x0100; // method
|
int ACC_NATIVE = 0x0100; // method
|
||||||
int ACC_INTERFACE = 0x0200; // class
|
int ACC_INTERFACE = 0x0200; // class
|
||||||
int ACC_ABSTRACT = 0x0400; // class, method
|
int ACC_ABSTRACT = 0x0400; // class, method
|
||||||
int ACC_STRICT = 0x0800; // method
|
int ACC_STRICT = 0x0800; // method
|
||||||
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
|
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
|
||||||
int ACC_ANNOTATION = 0x2000; // class
|
int ACC_ANNOTATION = 0x2000; // class
|
||||||
int ACC_ENUM = 0x4000; // class(?) field inner
|
int ACC_ENUM = 0x4000; // class(?) field inner
|
||||||
int ACC_MANDATED = 0x8000; // parameter
|
int ACC_MANDATED = 0x8000; // parameter, module, module *
|
||||||
|
int ACC_MODULE = 0x8000; // class
|
||||||
|
|
||||||
|
|
||||||
// ASM specific pseudo access flags
|
// ASM specific pseudo access flags
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -30,8 +30,8 @@ public final class SpringAsmInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ASM compatibility version for Spring's ASM visitor implementations:
|
* The ASM compatibility version for Spring's ASM visitor implementations:
|
||||||
* currently {@link Opcodes#ASM5}.
|
* currently {@link Opcodes#ASM6}.
|
||||||
*/
|
*/
|
||||||
public static final int ASM_VERSION = Opcodes.ASM5;
|
public static final int ASM_VERSION = Opcodes.ASM6;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue