8190287: Update JDK's internal ASM to ASMv6

Reviewed-by: alanb, mchung, sundar
This commit is contained in:
Kumar Srinivasan 2017-11-02 13:18:23 -07:00
parent 41f1222db0
commit 105a51b96d
83 changed files with 3795 additions and 1303 deletions

View File

@ -70,7 +70,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;
@ -85,7 +85,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);
@ -96,13 +96,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;
@ -118,7 +118,7 @@ public abstract class AnnotationVisitor {
* the actual value, whose type must be {@link Byte}, * the actual value, whose type must be {@link Byte},
* {@link Boolean}, {@link Character}, {@link Short}, * {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer} , {@link Long}, {@link Float}, {@link Double}, * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
* {@link String} or {@link Type} or OBJECT or ARRAY sort. This * {@link String} or {@link Type} of OBJECT or ARRAY sort. This
* value can also be an array of byte, boolean, short, char, int, * value can also be an array of byte, boolean, short, char, int,
* long, float or double values (this is equivalent to using * long, float or double values (this is equivalent to using
* {@link #visitArray visitArray} and visiting each array element * {@link #visitArray visitArray} and visiting each array element

View File

@ -133,7 +133,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;

View File

@ -72,31 +72,6 @@ import java.io.InputStream;
*/ */
public class ClassReader { public class ClassReader {
/**
* True to enable signatures support.
*/
static final boolean SIGNATURES = true;
/**
* True to enable annotations support.
*/
static final boolean ANNOTATIONS = true;
/**
* True to enable stack map frames support.
*/
static final boolean FRAMES = true;
/**
* True to enable bytecode writing support.
*/
static final boolean WRITER = true;
/**
* True to enable JSR_W and GOTO_W support.
*/
static final boolean RESIZE = true;
/** /**
* Flag to skip method code. If this class is set <code>CODE</code> * Flag to skip method code. If this class is set <code>CODE</code>
* attribute won't be visited. This can be used, for example, to retrieve * attribute won't be visited. This can be used, for example, to retrieve
@ -133,6 +108,21 @@ public class ClassReader {
*/ */
public static final int EXPAND_FRAMES = 8; public static final int EXPAND_FRAMES = 8;
/**
* Flag to expand the ASM pseudo instructions into an equivalent sequence of
* standard bytecode instructions. When resolving a forward jump it may
* happen that the signed 2 bytes offset reserved for it is not sufficient
* to store the bytecode offset. In this case the jump instruction is
* replaced with a temporary ASM pseudo instruction using an unsigned 2
* bytes offset (see Label#resolve). This internal flag is used to re-read
* classes containing such instructions, in order to replace them with
* standard instructions. In addition, when this flag is used, GOTO_W and
* JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
* infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
* converted back to a GOTO_W in ClassWriter cannot occur.
*/
static final int EXPAND_ASM_INSNS = 256;
/** /**
* The class to be parsed. <i>The content of this array must not be * The class to be parsed. <i>The content of this array must not be
* modified. This field is intended for {@link Attribute} sub classes, and * modified. This field is intended for {@link Attribute} sub classes, and
@ -195,7 +185,7 @@ public class ClassReader {
public ClassReader(final byte[] b, final int off, final int len) { public ClassReader(final byte[] b, final int off, final int len) {
this.b = b; this.b = b;
// checks the class version // checks the class version
if (readShort(off + 6) > Opcodes.V1_9) { if (readShort(off + 6) > Opcodes.V9) {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
// parses the constant pool // parses the constant pool
@ -234,6 +224,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;
@ -377,7 +369,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;
@ -584,11 +578,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();
@ -607,13 +604,11 @@ public class ClassReader {
enclosingName = readUTF8(items[item], c); enclosingName = readUTF8(items[item], c);
enclosingDesc = readUTF8(items[item] + 2, c); enclosingDesc = readUTF8(items[item] + 2, c);
} }
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED; access |= Opcodes.ACC_DEPRECATED;
@ -623,12 +618,16 @@ public class ClassReader {
} else if ("SourceDebugExtension".equals(attrName)) { } else if ("SourceDebugExtension".equals(attrName)) {
int len = readInt(u + 4); int len = readInt(u + 4);
sourceDebug = readUTF(u + 8, len, new char[len]); sourceDebug = readUTF(u + 8, len, new char[len]);
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("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++) {
@ -657,6 +656,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,
@ -664,19 +669,19 @@ public class ClassReader {
} }
// visits the class annotations and type annotations // visits the class annotations and type annotations
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), true)); classVisitor.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
classVisitor.visitAnnotation(readUTF8(v, c), false)); classVisitor.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -684,7 +689,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -726,6 +731,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.
* *
@ -762,24 +881,20 @@ public class ClassReader {
if ("ConstantValue".equals(attrName)) { if ("ConstantValue".equals(attrName)) {
int item = readUnsignedShort(u + 8); int item = readUnsignedShort(u + 8);
value = item == 0 ? null : readConst(item, c); value = item == 0 ? null : readConst(item, c);
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED; access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) { } else if ("Synthetic".equals(attrName)) {
access |= Opcodes.ACC_SYNTHETIC access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8; itanns = u + 8;
} else { } else {
Attribute attr = readAttribute(context.attrs, attrName, u + 8, Attribute attr = readAttribute(context.attrs, attrName, u + 8,
@ -801,19 +916,19 @@ public class ClassReader {
} }
// visits the field annotations and type annotations // visits the field annotations and type annotations
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), true)); fv.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
fv.visitAnnotation(readUTF8(v, c), false)); fv.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -821,7 +936,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -895,32 +1010,26 @@ public class ClassReader {
exceptions[j] = readClass(exception, c); exceptions[j] = readClass(exception, c);
exception += 2; exception += 2;
} }
} else if (SIGNATURES && "Signature".equals(attrName)) { } else if ("Signature".equals(attrName)) {
signature = readUTF8(u + 8, c); signature = readUTF8(u + 8, c);
} else if ("Deprecated".equals(attrName)) { } else if ("Deprecated".equals(attrName)) {
context.access |= Opcodes.ACC_DEPRECATED; context.access |= Opcodes.ACC_DEPRECATED;
} else if (ANNOTATIONS } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
&& "RuntimeVisibleAnnotations".equals(attrName)) {
anns = u + 8; anns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = u + 8; tanns = u + 8;
} else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) { } else if ("AnnotationDefault".equals(attrName)) {
dann = u + 8; dann = u + 8;
} else if ("Synthetic".equals(attrName)) { } else if ("Synthetic".equals(attrName)) {
context.access |= Opcodes.ACC_SYNTHETIC context.access |= Opcodes.ACC_SYNTHETIC
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
&& "RuntimeInvisibleAnnotations".equals(attrName)) {
ianns = u + 8; ianns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = u + 8; itanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
&& "RuntimeVisibleParameterAnnotations".equals(attrName)) {
mpanns = u + 8; mpanns = u + 8;
} else if (ANNOTATIONS } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
&& "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
impanns = u + 8; impanns = u + 8;
} else if ("MethodParameters".equals(attrName)) { } else if ("MethodParameters".equals(attrName)) {
methodParameters = u + 8; methodParameters = u + 8;
@ -953,7 +1062,7 @@ public class ClassReader {
* access, name and descriptor can have been changed, this is not * access, name and descriptor can have been changed, this is not
* important since they are not copied as is from the reader). * important since they are not copied as is from the reader).
*/ */
if (WRITER && mv instanceof MethodWriter) { if (mv instanceof MethodWriter) {
MethodWriter mw = (MethodWriter) mv; MethodWriter mw = (MethodWriter) mv;
if (mw.cw.cr == this && signature == mw.signature) { if (mw.cw.cr == this && signature == mw.signature) {
boolean sameExceptions = false; boolean sameExceptions = false;
@ -990,26 +1099,26 @@ public class ClassReader {
} }
// visits the method annotations // visits the method annotations
if (ANNOTATIONS && dann != 0) { if (dann != 0) {
AnnotationVisitor dv = mv.visitAnnotationDefault(); AnnotationVisitor dv = mv.visitAnnotationDefault();
readAnnotationValue(dann, c, null, dv); readAnnotationValue(dann, c, null, dv);
if (dv != null) { if (dv != null) {
dv.visitEnd(); dv.visitEnd();
} }
} }
if (ANNOTATIONS && anns != 0) { if (anns != 0) {
for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), true)); mv.visitAnnotation(readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && ianns != 0) { if (ianns != 0) {
for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
mv.visitAnnotation(readUTF8(v, c), false)); mv.visitAnnotation(readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && tanns != 0) { if (tanns != 0) {
for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -1017,7 +1126,7 @@ public class ClassReader {
context.typePath, readUTF8(v, c), true)); context.typePath, readUTF8(v, c), true));
} }
} }
if (ANNOTATIONS && itanns != 0) { if (itanns != 0) {
for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
v = readAnnotationTarget(context, v); v = readAnnotationTarget(context, v);
v = readAnnotationValues(v + 2, c, true, v = readAnnotationValues(v + 2, c, true,
@ -1025,10 +1134,10 @@ public class ClassReader {
context.typePath, readUTF8(v, c), false)); context.typePath, readUTF8(v, c), false));
} }
} }
if (ANNOTATIONS && mpanns != 0) { if (mpanns != 0) {
readParameterAnnotations(mv, context, mpanns, true); readParameterAnnotations(mv, context, mpanns, true);
} }
if (ANNOTATIONS && impanns != 0) { if (impanns != 0) {
readParameterAnnotations(mv, context, impanns, false); readParameterAnnotations(mv, context, impanns, false);
} }
@ -1075,7 +1184,7 @@ public class ClassReader {
int codeStart = u; int codeStart = u;
int codeEnd = u + codeLength; int codeEnd = u + codeLength;
Label[] labels = context.labels = new Label[codeLength + 2]; Label[] labels = context.labels = new Label[codeLength + 2];
readLabel(codeLength + 1, labels); createLabel(codeLength + 1, labels);
while (u < codeEnd) { while (u < codeEnd) {
int offset = u - codeStart; int offset = u - codeStart;
int opcode = b[u] & 0xFF; int opcode = b[u] & 0xFF;
@ -1085,11 +1194,16 @@ public class ClassReader {
u += 1; u += 1;
break; break;
case ClassWriter.LABEL_INSN: case ClassWriter.LABEL_INSN:
readLabel(offset + readShort(u + 1), labels); createLabel(offset + readShort(u + 1), labels);
u += 3;
break;
case ClassWriter.ASM_LABEL_INSN:
createLabel(offset + readUnsignedShort(u + 1), labels);
u += 3; u += 3;
break; break;
case ClassWriter.LABELW_INSN: case ClassWriter.LABELW_INSN:
readLabel(offset + readInt(u + 1), labels); case ClassWriter.ASM_LABELW_INSN:
createLabel(offset + readInt(u + 1), labels);
u += 5; u += 5;
break; break;
case ClassWriter.WIDE_INSN: case ClassWriter.WIDE_INSN:
@ -1104,9 +1218,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes // skips 0 to 3 padding bytes
u = u + 4 - (offset & 3); u = u + 4 - (offset & 3);
// reads instruction // reads instruction
readLabel(offset + readInt(u), labels); createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
readLabel(offset + readInt(u + 12), labels); createLabel(offset + readInt(u + 12), labels);
u += 4; u += 4;
} }
u += 12; u += 12;
@ -1115,9 +1229,9 @@ public class ClassReader {
// skips 0 to 3 padding bytes // skips 0 to 3 padding bytes
u = u + 4 - (offset & 3); u = u + 4 - (offset & 3);
// reads instruction // reads instruction
readLabel(offset + readInt(u), labels); createLabel(offset + readInt(u), labels);
for (int i = readInt(u + 4); i > 0; --i) { for (int i = readInt(u + 4); i > 0; --i) {
readLabel(offset + readInt(u + 12), labels); createLabel(offset + readInt(u + 12), labels);
u += 8; u += 8;
} }
u += 8; u += 8;
@ -1147,9 +1261,9 @@ public class ClassReader {
// reads the try catch entries to find the labels, and also visits them // reads the try catch entries to find the labels, and also visits them
for (int i = readUnsignedShort(u); i > 0; --i) { for (int i = readUnsignedShort(u); i > 0; --i) {
Label start = readLabel(readUnsignedShort(u + 2), labels); Label start = createLabel(readUnsignedShort(u + 2), labels);
Label end = readLabel(readUnsignedShort(u + 4), labels); Label end = createLabel(readUnsignedShort(u + 4), labels);
Label handler = readLabel(readUnsignedShort(u + 6), labels); Label handler = createLabel(readUnsignedShort(u + 6), labels);
String type = readUTF8(items[readUnsignedShort(u + 8)], c); String type = readUTF8(items[readUnsignedShort(u + 8)], c);
mv.visitTryCatchBlock(start, end, handler, type); mv.visitTryCatchBlock(start, end, handler, type);
u += 8; u += 8;
@ -1180,13 +1294,9 @@ public class ClassReader {
varTable = u + 8; varTable = u + 8;
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10); int label = readUnsignedShort(v + 10);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
label += readUnsignedShort(v + 12); label += readUnsignedShort(v + 12);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
v += 10; v += 10;
} }
} }
@ -1196,9 +1306,7 @@ public class ClassReader {
if ((context.flags & SKIP_DEBUG) == 0) { if ((context.flags & SKIP_DEBUG) == 0) {
for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
int label = readUnsignedShort(v + 10); int label = readUnsignedShort(v + 10);
if (labels[label] == null) { createDebugLabel(label, labels);
readLabel(label, labels).status |= Label.DEBUG;
}
Label l = labels[label]; Label l = labels[label];
while (l.line > 0) { while (l.line > 0) {
if (l.next == null) { if (l.next == null) {
@ -1210,17 +1318,15 @@ public class ClassReader {
v += 4; v += 4;
} }
} }
} else if (ANNOTATIONS } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeVisibleTypeAnnotations".equals(attrName)) {
tanns = readTypeAnnotations(mv, context, u + 8, true); tanns = readTypeAnnotations(mv, context, u + 8, true);
ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
: readUnsignedShort(tanns[0] + 1); : readUnsignedShort(tanns[0] + 1);
} else if (ANNOTATIONS } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
&& "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
itanns = readTypeAnnotations(mv, context, u + 8, false); itanns = readTypeAnnotations(mv, context, u + 8, false);
nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
: readUnsignedShort(itanns[0] + 1); : readUnsignedShort(itanns[0] + 1);
} else if (FRAMES && "StackMapTable".equals(attrName)) { } else if ("StackMapTable".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) { if ((context.flags & SKIP_FRAMES) == 0) {
stackMap = u + 10; stackMap = u + 10;
stackMapSize = readInt(u + 4); stackMapSize = readInt(u + 4);
@ -1244,7 +1350,7 @@ public class ClassReader {
* this by parsing the stack map table without a full decoding * this by parsing the stack map table without a full decoding
* (see below). * (see below).
*/ */
} else if (FRAMES && "StackMap".equals(attrName)) { } else if ("StackMap".equals(attrName)) {
if ((context.flags & SKIP_FRAMES) == 0) { if ((context.flags & SKIP_FRAMES) == 0) {
zip = false; zip = false;
stackMap = u + 10; stackMap = u + 10;
@ -1273,7 +1379,7 @@ public class ClassReader {
u += 2; u += 2;
// generates the first (implicit) stack map frame // generates the first (implicit) stack map frame
if (FRAMES && stackMap != 0) { if (stackMap != 0) {
/* /*
* for the first explicit frame the offset is not offset_delta + 1 * for the first explicit frame the offset is not offset_delta + 1
* but only offset_delta; setting the implicit frame offset to -1 * but only offset_delta; setting the implicit frame offset to -1
@ -1306,14 +1412,31 @@ public class ClassReader {
int v = readUnsignedShort(i + 1); int v = readUnsignedShort(i + 1);
if (v >= 0 && v < codeLength) { if (v >= 0 && v < codeLength) {
if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
readLabel(v, labels); createLabel(v, labels);
} }
} }
} }
} }
} }
if ((context.flags & EXPAND_ASM_INSNS) != 0
&& (context.flags & EXPAND_FRAMES) != 0) {
// Expanding the ASM pseudo instructions can introduce F_INSERT
// frames, even if the method does not currently have any frame.
// Also these inserted frames must be computed by simulating the
// effect of the bytecode instructions one by one, starting from the
// first one and the last existing frame (or the implicit first
// one). Finally, due to the way MethodWriter computes this (with
// the compute = INSERTED_FRAMES option), MethodWriter needs to know
// maxLocals before the first instruction is visited. For all these
// reasons we always visit the implicit first frame in this case
// (passing only maxLocals - the rest can be and is computed in
// MethodWriter).
mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
}
// visits the instructions // visits the instructions
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;
@ -1334,7 +1457,7 @@ public class ClassReader {
} }
// visits the frame for this offset, if any // visits the frame for this offset, if any
while (FRAMES && frame != null while (frame != null
&& (frame.offset == offset || frame.offset == -1)) { && (frame.offset == offset || frame.offset == -1)) {
// if there is a frame for this offset, makes the visitor visit // if there is a frame for this offset, makes the visitor visit
// it, and reads the next frame if there is one. // it, and reads the next frame if there is one.
@ -1346,6 +1469,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);
@ -1354,6 +1480,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 (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;
@ -1378,9 +1511,47 @@ public class ClassReader {
u += 3; u += 3;
break; break;
case ClassWriter.LABELW_INSN: case ClassWriter.LABELW_INSN:
mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]); mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
+ readInt(u + 1)]);
u += 5; u += 5;
break; break;
case ClassWriter.ASM_LABEL_INSN: {
// changes temporary opcodes 202 to 217 (inclusive), 218
// and 219 to IFEQ ... JSR (inclusive), IFNULL and
// IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
Label target = labels[offset + readUnsignedShort(u + 1)];
// replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
// <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
// the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
// and where <L> designates the instruction just after
// the GOTO_W.
if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
mv.visitJumpInsn(opcode + 33, target);
} else {
opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1;
Label endif = createLabel(offset + 3, labels);
mv.visitJumpInsn(opcode, endif);
mv.visitJumpInsn(200, target); // GOTO_W
// endif designates the instruction just after GOTO_W,
// and is visited as part of the next instruction. Since
// it is a jump target, we need to insert a frame here.
insertFrame = true;
}
u += 3;
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) {
@ -1636,8 +1807,8 @@ public class ClassReader {
for (int j = readUnsignedShort(u + 1); j > 0; --j) { for (int j = readUnsignedShort(u + 1); j > 0; --j) {
int start = readUnsignedShort(u + 3); int start = readUnsignedShort(u + 3);
int length = readUnsignedShort(u + 5); int length = readUnsignedShort(u + 5);
readLabel(start, context.labels); createLabel(start, context.labels);
readLabel(start + length, context.labels); createLabel(start + length, context.labels);
u += 6; u += 6;
} }
u += 3; u += 3;
@ -1716,8 +1887,8 @@ public class ClassReader {
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
int start = readUnsignedShort(u); int start = readUnsignedShort(u);
int length = readUnsignedShort(u + 2); int length = readUnsignedShort(u + 2);
context.start[i] = readLabel(start, context.labels); context.start[i] = createLabel(start, context.labels);
context.end[i] = readLabel(start + length, context.labels); context.end[i] = createLabel(start + length, context.labels);
context.index[i] = readUnsignedShort(u + 4); context.index[i] = readUnsignedShort(u + 4);
u += 6; u += 6;
} }
@ -2137,7 +2308,7 @@ public class ClassReader {
} }
} }
frame.offset += delta + 1; frame.offset += delta + 1;
readLabel(frame.offset, labels); createLabel(frame.offset, labels);
return stackMap; return stackMap;
} }
@ -2190,7 +2361,7 @@ public class ClassReader {
v += 2; v += 2;
break; break;
default: // Uninitialized default: // Uninitialized
frame[index] = readLabel(readUnsignedShort(v), labels); frame[index] = createLabel(readUnsignedShort(v), labels);
v += 2; v += 2;
} }
return v; return v;
@ -2216,6 +2387,39 @@ public class ClassReader {
return labels[offset]; return labels[offset];
} }
/**
* Creates a label without the Label.DEBUG flag set, for the given offset.
* The label is created with a call to {@link #readLabel} and its
* Label.DEBUG flag is cleared.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
* @return a Label without the Label.DEBUG flag set.
*/
private Label createLabel(int offset, Label[] labels) {
Label label = readLabel(offset, labels);
label.status &= ~Label.DEBUG;
return label;
}
/**
* Creates a label with the Label.DEBUG flag set, if there is no already
* existing label for the given offset (otherwise does nothing). The label
* is created with a call to {@link #readLabel}.
*
* @param offset
* a bytecode offset in a method.
* @param labels
* the already created labels, indexed by their offset.
*/
private void createDebugLabel(int offset, Label[] labels) {
if (labels[offset] == null) {
readLabel(offset, labels).status |= Label.DEBUG;
}
}
/** /**
* Returns the start index of the attribute_info structure of this class. * Returns the start index of the attribute_info structure of this class.
* *
@ -2470,6 +2674,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
@ -2484,44 +2702,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
return readUTF8(items[readUnsignedShort(index)], buf);
} }
/** /**
* Reads a CONSTANT_Module_info item in {@code b}. This method is intended * Reads a module constant pool item in {@link #b b}. <i>This method is
* for {@link Attribute} sub classes, and is normally not needed by class * intended for {@link Attribute} sub classes, and is normally not needed by
* generators or adapters.</i> * class generators or adapters.</i>
* *
* @param index * @param index
* the start index of an unsigned short value in {@link #b b}, * the start index of an unsigned short value in {@link #b b},
* whose value is the index of a module constant pool item. * whose value is the index of a module constant pool item.
* @param buf * @param buf
* buffer to be used to read the item. This buffer must be * buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized. * sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified module item. * @return the String corresponding to the specified module item.
*/ */
public String readModule(int index, char[] buf) { public String readModule(final int index, final char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf); return readStringish(index, buf);
} }
/** /**
* Reads a CONSTANT_Package_info item in {@code b}. This method is * Reads a module constant pool item in {@link #b b}. <i>This method is
* intended for {@link Attribute} sub slasses, and is normally not needed * intended for {@link Attribute} sub classes, and is normally not needed by
* by class generators or adapters.</i> * class generators or adapters.</i>
* *
* @param index * @param index
* the start index of an unsigned short value in {@link #b b}, * the start index of an unsigned short value in {@link #b b},
* whose value is the index of a package constant pool item. * whose value is the index of a module constant pool item.
* @param buf * @param buf
* buffer to be used to read the item. This buffer must be * buffer to be used to read the item. This buffer must be
* sufficiently large. It is not automatically resized. * sufficiently large. It is not automatically resized.
* @return the String corresponding to the specified package item. * @return the String corresponding to the specified module item.
*/ */
public String readPackage(int index, char[] buf) { public String readPackage(final int index, final char[] buf) {
return readUTF8(items[readUnsignedShort(index)], buf); return readStringish(index, buf);
} }
/** /**
@ -2550,8 +2765,6 @@ public class ClassReader {
case ClassWriter.DOUBLE: case ClassWriter.DOUBLE:
return Double.longBitsToDouble(readLong(index)); return Double.longBitsToDouble(readLong(index));
case ClassWriter.CLASS: case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
return Type.getObjectType(readUTF8(index, buf)); return Type.getObjectType(readUTF8(index, buf));
case ClassWriter.STR: case ClassWriter.STR:
return readUTF8(index, buf); return readUTF8(index, buf);

View File

@ -61,7 +61,7 @@ package jdk.internal.org.objectweb.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>.
@ -72,7 +72,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;
@ -87,7 +87,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);
@ -98,13 +98,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;
@ -160,6 +160,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.

View File

@ -87,8 +87,8 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor#visitFrame} method are ignored, and the stack map * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
* frames are recomputed from the methods bytecode. The arguments of the * frames are recomputed from the methods bytecode. The arguments of the
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies * recomputed from the bytecode. In other words, COMPUTE_FRAMES implies
* computeMaxs. * COMPUTE_MAXS.
* *
* @see #ClassWriter(int) * @see #ClassWriter(int)
*/ */
@ -196,6 +196,27 @@ public class ClassWriter extends ClassVisitor {
*/ */
static final int WIDE_INSN = 17; static final int WIDE_INSN = 17;
/**
* The type of the ASM pseudo instructions with an unsigned 2 bytes offset
* label (see Label#resolve).
*/
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
* frame can only be used if the frame content can be computed from the
* previous existing frame and from the instructions between this existing
* frame and the inserted one, without any knowledge of the type hierarchy.
* This kind of frame is only used when an unconditional jump is inserted in
* a method while expanding an ASM pseudo instruction (see ClassReader).
*/
static final int F_INSERT = 256;
/** /**
* The instruction types of all JVM opcodes. * The instruction types of all JVM opcodes.
*/ */
@ -284,7 +305,7 @@ public class ClassWriter extends ClassVisitor {
/** /**
* 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;
@ -433,6 +454,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,25 +549,19 @@ public class ClassWriter extends ClassVisitor {
MethodWriter lastMethod; MethodWriter lastMethod;
/** /**
* <tt>true</tt> if the maximum stack size and number of local variables * Indicates what must be automatically computed.
* must be automatically computed. *
* @see MethodWriter#compute
*/ */
private boolean computeMaxs; private int compute;
/** /**
* <tt>true</tt> if the stack map frames must be recomputed from scratch. * <tt>true</tt> if some methods have wide forward jumps using ASM pseudo
* instructions, which need to be expanded into sequences of standard
* bytecode instructions. In this case the class is re-read and re-written
* with a ClassReader -> ClassWriter chain to perform this transformation.
*/ */
private boolean computeFrames; boolean hasAsmInsns;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
* {@link MethodWriter#resizeInstructions} method cannot transform existing
* stack map tables, and so produces potentially invalid classes when it is
* executed. In this case the class is reread and rewritten with the
* {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
* stack map tables when this option is used).
*/
boolean invalidFrames;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Static initializer // Static initializer
@ -552,11 +572,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"
+ "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ"; + "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');
} }
@ -610,8 +630,9 @@ public class ClassWriter extends ClassVisitor {
// // temporary opcodes used internally by ASM - see Label and // // temporary opcodes used internally by ASM - see Label and
// MethodWriter // MethodWriter
// for (i = 202; i < 220; ++i) { // for (i = 202; i < 220; ++i) {
// b[i] = 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;
@ -644,7 +665,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];
@ -653,8 +674,9 @@ public class ClassWriter extends ClassVisitor {
key2 = new Item(); key2 = new Item();
key3 = new Item(); key3 = new Item();
key4 = new Item(); key4 = new Item();
this.computeMaxs = (flags & COMPUTE_MAXS) != 0; this.compute = (flags & COMPUTE_FRAMES) != 0 ? MethodWriter.FRAMES
this.computeFrames = (flags & COMPUTE_FRAMES) != 0; : ((flags & COMPUTE_MAXS) != 0 ? MethodWriter.MAXS
: MethodWriter.NOTHING);
} }
/** /**
@ -684,9 +706,9 @@ public class ClassWriter extends ClassVisitor {
* @param flags * @param flags
* option flags that can be used to modify the default behavior * option flags that can be used to modify the default behavior
* of this class. <i>These option flags do not affect methods * of this class. <i>These option flags do not affect methods
* that are copied as is in the new class. This means that the * that are copied as is in the new class. This means that
* maximum stack size nor the stack frames will be computed for * neither the maximum stack size nor the stack frames will be
* these methods</i>. See {@link #COMPUTE_MAXS}, * computed for these methods</i>. See {@link #COMPUTE_MAXS},
* {@link #COMPUTE_FRAMES}. * {@link #COMPUTE_FRAMES}.
*/ */
public ClassWriter(final ClassReader classReader, final int flags) { public ClassWriter(final ClassReader classReader, final int flags) {
@ -705,9 +727,9 @@ public class ClassWriter extends ClassVisitor {
final String[] interfaces) { final String[] interfaces) {
this.version = version; this.version = version;
this.access = access; this.access = access;
this.name = (name == null) ? 0 : newClass(name); this.name = newClass(name);
thisName = name; thisName = name;
if (ClassReader.SIGNATURES && signature != null) { if (signature != null) {
this.signature = newUTF8(signature); this.signature = newUTF8(signature);
} }
this.superName = superName == null ? 0 : newClass(superName); this.superName = superName == null ? 0 : newClass(superName);
@ -731,6 +753,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) {
@ -743,9 +773,6 @@ public class ClassWriter extends ClassVisitor {
@Override @Override
public final AnnotationVisitor visitAnnotation(final String desc, public final AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) { final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write type, and reserve space for values count // write type, and reserve space for values count
bv.putShort(newUTF8(desc)).putShort(0); bv.putShort(newUTF8(desc)).putShort(0);
@ -763,9 +790,6 @@ public class ClassWriter extends ClassVisitor {
@Override @Override
public final AnnotationVisitor visitTypeAnnotation(int typeRef, public final AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, final String desc, final boolean visible) { TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write target_type and target_info // write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv); AnnotationWriter.putTarget(typeRef, typePath, bv);
@ -805,7 +829,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);
@ -830,7 +854,7 @@ public class ClassWriter extends ClassVisitor {
public final MethodVisitor visitMethod(final int access, final String name, public final MethodVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) { final String desc, final String signature, final String[] exceptions) {
return new MethodWriter(this, access, name, desc, signature, return new MethodWriter(this, access, name, desc, signature,
exceptions, computeMaxs, computeFrames); exceptions, compute);
} }
@Override @Override
@ -874,7 +898,7 @@ public class ClassWriter extends ClassVisitor {
size += 8 + bootstrapMethods.length; size += 8 + bootstrapMethods.length;
newUTF8("BootstrapMethods"); newUTF8("BootstrapMethods");
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
++attributeCount; ++attributeCount;
size += 8; size += 8;
newUTF8("Signature"); newUTF8("Signature");
@ -912,26 +936,31 @@ public class ClassWriter extends ClassVisitor {
size += 8 + innerClasses.length; size += 8 + innerClasses.length;
newUTF8("InnerClasses"); newUTF8("InnerClasses");
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
++attributeCount; ++attributeCount;
size += 8 + anns.getSize(); size += 8 + anns.getSize();
newUTF8("RuntimeVisibleAnnotations"); newUTF8("RuntimeVisibleAnnotations");
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
++attributeCount; ++attributeCount;
size += 8 + ianns.getSize(); size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations"); newUTF8("RuntimeInvisibleAnnotations");
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
++attributeCount; ++attributeCount;
size += 8 + tanns.getSize(); size += 8 + tanns.getSize();
newUTF8("RuntimeVisibleTypeAnnotations"); newUTF8("RuntimeVisibleTypeAnnotations");
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
++attributeCount; ++attributeCount;
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);
@ -968,7 +997,7 @@ public class ClassWriter extends ClassVisitor {
bootstrapMethodsCount); bootstrapMethodsCount);
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
out.putShort(newUTF8("Signature")).putInt(2).putShort(signature); out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
} }
if (sourceFile != 0) { if (sourceFile != 0) {
@ -979,6 +1008,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);
@ -997,41 +1031,46 @@ public class ClassWriter extends ClassVisitor {
out.putInt(innerClasses.length + 2).putShort(innerClassesCount); out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
out.putByteArray(innerClasses.data, 0, innerClasses.length); out.putByteArray(innerClasses.data, 0, innerClasses.length);
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
out.putShort(newUTF8("RuntimeVisibleAnnotations")); out.putShort(newUTF8("RuntimeVisibleAnnotations"));
anns.put(out); anns.put(out);
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
out.putShort(newUTF8("RuntimeInvisibleAnnotations")); out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out); ianns.put(out);
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
out.putShort(newUTF8("RuntimeVisibleTypeAnnotations")); out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out); tanns.put(out);
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations")); out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out); itanns.put(out);
} }
if (attrs != null) { if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out); attrs.put(this, null, 0, -1, -1, out);
} }
if (invalidFrames) { 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;
innerClassesCount = 0; moduleWriter = null;
innerClasses = null;
bootstrapMethodsCount = 0;
bootstrapMethods = null;
firstField = null; firstField = null;
lastField = null; lastField = null;
firstMethod = null; firstMethod = null;
lastMethod = null; lastMethod = null;
computeMaxs = false; compute =
computeFrames = true; hasFrames ? MethodWriter.INSERTED_FRAMES : MethodWriter.NOTHING;
invalidFrames = false; hasAsmInsns = false;
new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); new ClassReader(out.data).accept(this,
(hasFrames ? ClassReader.EXPAND_FRAMES : 0)
| ClassReader.EXPAND_ASM_INSNS);
return toByteArray(); return toByteArray();
} }
return out.data; return out.data;
@ -1078,16 +1117,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;
@ -1136,20 +1175,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);
} }
@ -1167,72 +1207,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 module name to the constant pool.
*
* 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 value
* the module name
* @return the index of a new or already existing module reference item.
*/
public int newModule(String value) {
key2.set(MODULE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(MODULE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.index;
}
/**
* Adds a package name to the constant pool.
*
* 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 value
* the internal name of the package.
* @return the index of a new or already existing package reference item.
*/
public int newPackage(String value) {
key2.set(PACKAGE, value, null, null);
Item result = get(key2);
if (result == null) {
pool.put12(PACKAGE, newUTF8(value));
result = new Item(index++, key2);
put(result);
}
return result.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;
} }
/** /**
@ -1247,7 +1222,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;
} }
/** /**
@ -1628,25 +1633,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

View File

@ -0,0 +1,85 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm;
/**
* Information about the input stack map frame at the "current" instruction of a
* method. This is implemented as a Frame subclass for a "basic block"
* containing only one instruction.
*
* @author Eric Bruneton
*/
class CurrentFrame extends Frame {
/**
* Sets this CurrentFrame to the input stack map frame of the next "current"
* instruction, i.e. the instruction just after the given one. It is assumed
* that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed.
*/
@Override
void execute(int opcode, int arg, ClassWriter cw, Item item) {
super.execute(opcode, arg, cw, item);
Frame successor = new Frame();
merge(cw, successor, 0);
set(successor);
owner.inputStackTop = 0;
}
}

View File

@ -69,7 +69,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;
@ -84,7 +84,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);
@ -95,13 +95,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;

View File

@ -147,7 +147,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 {
@ -158,7 +158,7 @@ final class FieldWriter extends FieldVisitor {
this.access = access; this.access = access;
this.name = cw.newUTF8(name); this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc); this.desc = cw.newUTF8(desc);
if (ClassReader.SIGNATURES && signature != null) { if (signature != null) {
this.signature = cw.newUTF8(signature); this.signature = cw.newUTF8(signature);
} }
if (value != null) { if (value != null) {
@ -173,9 +173,6 @@ final class FieldWriter extends FieldVisitor {
@Override @Override
public AnnotationVisitor visitAnnotation(final String desc, public AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) { final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write type, and reserve space for values count // write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0); bv.putShort(cw.newUTF8(desc)).putShort(0);
@ -193,9 +190,6 @@ final class FieldWriter extends FieldVisitor {
@Override @Override
public AnnotationVisitor visitTypeAnnotation(final int typeRef, public AnnotationVisitor visitTypeAnnotation(final int typeRef,
final TypePath typePath, final String desc, final boolean visible) { final TypePath typePath, final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector(); ByteVector bv = new ByteVector();
// write target_type and target_info // write target_type and target_info
AnnotationWriter.putTarget(typeRef, typePath, bv); AnnotationWriter.putTarget(typeRef, typePath, bv);
@ -249,23 +243,23 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("Deprecated"); cw.newUTF8("Deprecated");
size += 6; size += 6;
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
cw.newUTF8("Signature"); cw.newUTF8("Signature");
size += 8; size += 8;
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
cw.newUTF8("RuntimeVisibleAnnotations"); cw.newUTF8("RuntimeVisibleAnnotations");
size += 8 + anns.getSize(); size += 8 + anns.getSize();
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
cw.newUTF8("RuntimeInvisibleAnnotations"); cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize(); size += 8 + ianns.getSize();
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations"); cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize(); size += 8 + tanns.getSize();
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations"); cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize(); size += 8 + itanns.getSize();
} }
@ -299,19 +293,19 @@ final class FieldWriter extends FieldVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) { if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
++attributeCount; ++attributeCount;
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
++attributeCount; ++attributeCount;
} }
if (attrs != null) { if (attrs != null) {
@ -331,23 +325,23 @@ final class FieldWriter extends FieldVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) { if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0); out.putShort(cw.newUTF8("Deprecated")).putInt(0);
} }
if (ClassReader.SIGNATURES && signature != 0) { if (signature != 0) {
out.putShort(cw.newUTF8("Signature")); out.putShort(cw.newUTF8("Signature"));
out.putInt(2).putShort(signature); out.putInt(2).putShort(signature);
} }
if (ClassReader.ANNOTATIONS && anns != null) { if (anns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations")); out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
anns.put(out); anns.put(out);
} }
if (ClassReader.ANNOTATIONS && ianns != null) { if (ianns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations")); out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out); ianns.put(out);
} }
if (ClassReader.ANNOTATIONS && tanns != null) { if (tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations")); out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out); tanns.put(out);
} }
if (ClassReader.ANNOTATIONS && itanns != null) { if (itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations")); out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out); itanns.put(out);
} }

View File

@ -63,7 +63,7 @@ package jdk.internal.org.objectweb.asm;
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
final class Frame { class Frame {
/* /*
* Frames are computed in a two steps process: during the visit of each * Frames are computed in a two steps process: during the visit of each
@ -525,7 +525,7 @@ final class Frame {
* When the stack map frames are completely computed, this field is the * When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}. * actual number of types in {@link #outputStack}.
*/ */
private int outputStackTop; int outputStackTop;
/** /**
* Number of types that are initialized in the basic block. * Number of types that are initialized in the basic block.
@ -549,6 +549,110 @@ final class Frame {
*/ */
private int[] initializations; private int[] initializations;
/**
* Sets this frame to the given value.
*
* @param cw
* the ClassWriter to which this label belongs.
* @param nLocal
* the number of local variables.
* @param local
* the local variable types. Primitive types are represented by
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
* represented by a single element). Reference types are
* represented by String objects (representing internal names),
* and uninitialized types by Label objects (this label
* designates the NEW instruction that created this uninitialized
* value).
* @param nStack
* the number of operand stack elements.
* @param stack
* the operand stack types (same format as the "local" array).
*/
final void set(ClassWriter cw, final int nLocal, final Object[] local,
final int nStack, final Object[] stack) {
int i = convert(cw, nLocal, local, inputLocals);
while (i < local.length) {
inputLocals[i++] = TOP;
}
int nStackTop = 0;
for (int j = 0; j < nStack; ++j) {
if (stack[j] == Opcodes.LONG || stack[j] == Opcodes.DOUBLE) {
++nStackTop;
}
}
inputStack = new int[nStack + nStackTop];
convert(cw, nStack, stack, inputStack);
outputStackTop = 0;
initializationCount = 0;
}
/**
* Converts types from the MethodWriter.visitFrame() format to the Frame
* format.
*
* @param cw
* the ClassWriter to which this label belongs.
* @param nInput
* the number of types to convert.
* @param input
* the types to convert. Primitive types are represented by
* {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
* {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
* {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
* {@link Opcodes#UNINITIALIZED_THIS} (long and double are
* represented by a single element). Reference types are
* represented by String objects (representing internal names),
* and uninitialized types by Label objects (this label
* designates the NEW instruction that created this uninitialized
* value).
* @param output
* where to store the converted types.
* @return the number of output elements.
*/
private static int convert(ClassWriter cw, int nInput, Object[] input,
int[] output) {
int i = 0;
for (int j = 0; j < nInput; ++j) {
if (input[j] instanceof Integer) {
output[i++] = BASE | ((Integer) input[j]).intValue();
if (input[j] == Opcodes.LONG || input[j] == Opcodes.DOUBLE) {
output[i++] = TOP;
}
} else if (input[j] instanceof String) {
output[i++] = type(cw, Type.getObjectType((String) input[j])
.getDescriptor());
} else {
output[i++] = UNINITIALIZED
| cw.addUninitializedType("",
((Label) input[j]).position);
}
}
return i;
}
/**
* Sets this frame to the value of the given frame. WARNING: after this
* method is called the two frames share the same data structures. It is
* recommended to discard the given frame f to avoid unexpected side
* effects.
*
* @param f
* The new frame value.
*/
final void set(final Frame f) {
inputLocals = f.inputLocals;
inputStack = f.inputStack;
outputLocals = f.outputLocals;
outputStack = f.outputStack;
outputStackTop = f.outputStackTop;
initializationCount = f.initializationCount;
initializations = f.initializations;
}
/** /**
* Returns the output frame local variable type at the given index. * Returns the output frame local variable type at the given index.
* *
@ -614,7 +718,7 @@ final class Frame {
} }
// pushes the type on the output stack // pushes the type on the output stack
outputStack[outputStackTop++] = type; outputStack[outputStackTop++] = type;
// updates the maximun height reached by the output stack, if needed // updates the maximum height reached by the output stack, if needed
int top = owner.inputStackTop + outputStackTop; int top = owner.inputStackTop + outputStackTop;
if (top > owner.outputStackMax) { if (top > owner.outputStackMax) {
owner.outputStackMax = top; owner.outputStackMax = top;
@ -650,7 +754,7 @@ final class Frame {
* a type descriptor. * a type descriptor.
* @return the int encoding of the given type. * @return the int encoding of the given type.
*/ */
private static int type(final ClassWriter cw, final String desc) { static int type(final ClassWriter cw, final String desc) {
String t; String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) { switch (desc.charAt(index)) {
@ -838,7 +942,7 @@ final class Frame {
* @param maxLocals * @param maxLocals
* the maximum number of local variables of this method. * the maximum number of local variables of this method.
*/ */
void initInputFrame(final ClassWriter cw, final int access, final void initInputFrame(final ClassWriter cw, final int access,
final Type[] args, final int maxLocals) { final Type[] args, final int maxLocals) {
inputLocals = new int[maxLocals]; inputLocals = new int[maxLocals];
inputStack = new int[0]; inputStack = new int[0];
@ -981,7 +1085,7 @@ final class Frame {
case Opcodes.AALOAD: case Opcodes.AALOAD:
pop(1); pop(1);
t1 = pop(); t1 = pop();
push(ELEMENT_OF + t1); push(t1 == NULL ? t1 : ELEMENT_OF + t1);
break; break;
case Opcodes.ISTORE: case Opcodes.ISTORE:
case Opcodes.FSTORE: case Opcodes.FSTORE:
@ -1312,7 +1416,7 @@ final class Frame {
* @return <tt>true</tt> if the input frame of the given label has been * @return <tt>true</tt> if the input frame of the given label has been
* changed by this operation. * changed by this operation.
*/ */
boolean merge(final ClassWriter cw, final Frame frame, final int edge) { final boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
boolean changed = false; boolean changed = false;
int i, s, dim, kind, t; int i, s, dim, kind, t;

View File

@ -80,6 +80,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
@ -239,12 +240,12 @@ final class Item {
this.strVal3 = strVal3; this.strVal3 = strVal3;
switch (type) { switch (type) {
case ClassWriter.CLASS: case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
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;

View File

@ -389,13 +389,12 @@ public class Label {
* the position of this label in the bytecode. * the position of this label in the bytecode.
* @param data * @param data
* the bytecode of the method. * the bytecode of the method.
* @return <tt>true</tt> if a blank that was left for this label was to * @return <tt>true</tt> if a blank that was left for this label was too
* small to store the offset. In such a case the corresponding jump * small to store the offset. In such a case the corresponding jump
* instruction is replaced with a pseudo instruction (using unused * instruction is replaced with a pseudo instruction (using unused
* opcodes) using an unsigned two bytes offset. These pseudo * opcodes) using an unsigned two bytes offset. These pseudo
* instructions will need to be replaced with true instructions with * instructions will be replaced with standard bytecode instructions
* wider offsets (4 bytes instead of 2). This is done in * with wider offsets (4 bytes instead of 2), in ClassReader.
* {@link MethodWriter#resizeInstructions}.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if this label has already been resolved, or if it has not * if this label has already been resolved, or if it has not
* been created by the given code writer. * been created by the given code writer.
@ -454,7 +453,7 @@ public class Label {
* @return the first label of the series to which this label belongs. * @return the first label of the series to which this label belongs.
*/ */
Label getFirst() { Label getFirst() {
return !ClassReader.FRAMES || frame == null ? this : frame.owner; return frame == null ? this : frame.owner;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -86,7 +86,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;
@ -101,7 +101,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);
@ -112,13 +112,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;

View File

@ -0,0 +1,219 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm;
/**
* A visitor to visit a Java module. The methods of this class must be called in
* the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
* <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
* <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
*
* The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
* {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
* take as parameter a package name or a module name. Unlike the other names which are internal names
* (names separated by slash), module and package names are qualified names (names separated by dot).
*
* @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;
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
*/
public ModuleVisitor(final int api) {
this(api, null);
}
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
* @param mv
* the module 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 internal name of the main class of the current module.
*/
public void visitMainClass(String mainClass) {
if (mv != null) {
mv.visitMainClass(mainClass);
}
}
/**
* Visit a package of the current module.
*
* @param packaze the qualified name of a package.
*/
public void visitPackage(String packaze) {
if (mv != null) {
mv.visitPackage(packaze);
}
}
/**
* Visits a dependence of the current module.
*
* @param module the qualified 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 qualified 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 the qualified 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 qualified 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 the qualified 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 internal name of an interface or a 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);
}
}
/**
* Visits the end of the module. This method, which is the last one to be
* called, is used to inform the visitor that everything have been visited.
*/
public void visitEnd() {
if (mv != null) {
mv.visitEnd();
}
}
}

View File

@ -0,0 +1,322 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.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);
}
}
}

View File

@ -70,13 +70,13 @@ package jdk.internal.org.objectweb.asm;
* @author Eric Bruneton * @author Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
@SuppressWarnings("deprecation") // for Integer(int) constructor
public interface Opcodes { public interface Opcodes {
// ASM API versions // ASM API versions
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
@ -88,7 +88,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; int V9 = 0 << 16 | 53;
// access flags // access flags
@ -99,18 +99,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
@ -177,15 +182,17 @@ public interface Opcodes {
*/ */
int F_SAME1 = 4; int F_SAME1 = 4;
// For reference comparison purposes, construct new instances // Do not try to change the following code to use auto-boxing,
// instead of using valueOf() or autoboxing. // these values are compared by reference and not by value
Integer TOP = new Integer(0); // The constructor of Integer was deprecated in 9
Integer INTEGER = new Integer(1); // but we are stuck with it by backward compatibility
Integer FLOAT = new Integer(2); @SuppressWarnings("deprecation") Integer TOP = new Integer(0);
Integer DOUBLE = new Integer(3); @SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
Integer LONG = new Integer(4); @SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
Integer NULL = new Integer(5); @SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
Integer UNINITIALIZED_THIS = new Integer(6); @SuppressWarnings("deprecation") Integer LONG = new Integer(4);
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem) // opcodes // visit method (- = idem)

View File

@ -406,7 +406,16 @@ public class Type {
*/ */
public static Type getReturnType(final String methodDescriptor) { public static Type getReturnType(final String methodDescriptor) {
char[] buf = methodDescriptor.toCharArray(); char[] buf = methodDescriptor.toCharArray();
return getType(buf, methodDescriptor.indexOf(')') + 1); int off = 1;
while (true) {
char car = buf[off++];
if (car == ')') {
return getType(buf, off);
} else if (car == 'L') {
while (buf[off++] != ';') {
}
}
}
} }
/** /**

View File

@ -112,7 +112,7 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes
* *
* @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 adapter delegates calls. * the method visitor to which this adapter delegates calls.
* @param access * @param access

View File

@ -170,7 +170,7 @@ public class AnalyzerAdapter extends MethodVisitor {
*/ */
public AnalyzerAdapter(final String owner, final int access, public AnalyzerAdapter(final String owner, final int access,
final String name, final String desc, final MethodVisitor mv) { final String name, final String desc, final MethodVisitor mv) {
this(Opcodes.ASM5, owner, access, name, desc, mv); this(Opcodes.ASM6, owner, access, name, desc, mv);
if (getClass() != AnalyzerAdapter.class) { if (getClass() != AnalyzerAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -181,7 +181,7 @@ public class AnalyzerAdapter extends 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 owner * @param owner
* the owner's class name. * the owner's class name.
* @param access * @param access
@ -690,6 +690,8 @@ public class AnalyzerAdapter extends MethodVisitor {
t1 = pop(); t1 = pop();
if (t1 instanceof String) { if (t1 instanceof String) {
pushDesc(((String) t1).substring(1)); pushDesc(((String) t1).substring(1));
} else if (t1 == Opcodes.NULL) {
push(t1);
} else { } else {
push("java/lang/Object"); push("java/lang/Object");
} }

View File

@ -73,7 +73,7 @@ public class AnnotationRemapper extends AnnotationVisitor {
public AnnotationRemapper(final AnnotationVisitor av, public AnnotationRemapper(final AnnotationVisitor av,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, av, remapper); this(Opcodes.ASM6, av, remapper);
} }
protected AnnotationRemapper(final int api, final AnnotationVisitor av, protected AnnotationRemapper(final int api, final AnnotationVisitor av,

View File

@ -59,10 +59,14 @@
package jdk.internal.org.objectweb.asm.commons; package jdk.internal.org.objectweb.asm.commons;
import java.util.List;
import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -78,7 +82,7 @@ public class ClassRemapper extends ClassVisitor {
protected String className; protected String className;
public ClassRemapper(final ClassVisitor cv, final Remapper remapper) { public ClassRemapper(final ClassVisitor cv, final Remapper remapper) {
this(Opcodes.ASM5, cv, remapper); this(Opcodes.ASM6, cv, remapper);
} }
protected ClassRemapper(final int api, final ClassVisitor cv, protected ClassRemapper(final int api, final ClassVisitor cv,
@ -96,6 +100,12 @@ public class ClassRemapper extends ClassVisitor {
interfaces == null ? null : remapper.mapTypes(interfaces)); interfaces == null ? null : remapper.mapTypes(interfaces));
} }
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
ModuleVisitor mv = super.visitModule(remapper.mapModuleName(name), flags, version);
return mv == null ? null : createModuleRemapper(mv);
}
@Override @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
@ -111,6 +121,18 @@ public class ClassRemapper extends ClassVisitor {
return av == null ? null : createAnnotationRemapper(av); return av == null ? null : createAnnotationRemapper(av);
} }
@Override
public void visitAttribute(Attribute attr) {
if (attr instanceof ModuleHashesAttribute) {
ModuleHashesAttribute hashesAttr = new ModuleHashesAttribute();
List<String> modules = hashesAttr.modules;
for(int i = 0; i < modules.size(); i++) {
modules.set(i, remapper.mapModuleName(modules.get(i)));
}
}
super.visitAttribute(attr);
}
@Override @Override
public FieldVisitor visitField(int access, String name, String desc, public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) { String signature, Object value) {
@ -158,4 +180,8 @@ public class ClassRemapper extends ClassVisitor {
protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) { protected AnnotationVisitor createAnnotationRemapper(AnnotationVisitor av) {
return new AnnotationRemapper(av, remapper); return new AnnotationRemapper(av, remapper);
} }
protected ModuleVisitor createModuleRemapper(ModuleVisitor mv) {
return new ModuleRemapper(mv, remapper);
}
} }

View File

@ -75,7 +75,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
private int maxSize; private int maxSize;
public CodeSizeEvaluator(final MethodVisitor mv) { public CodeSizeEvaluator(final MethodVisitor mv) {
this(Opcodes.ASM5, mv); this(Opcodes.ASM6, mv);
} }
protected CodeSizeEvaluator(final int api, final MethodVisitor mv) { protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {

View File

@ -74,7 +74,7 @@ public class FieldRemapper extends FieldVisitor {
private final Remapper remapper; private final Remapper remapper;
public FieldRemapper(final FieldVisitor fv, final Remapper remapper) { public FieldRemapper(final FieldVisitor fv, final Remapper remapper) {
this(Opcodes.ASM5, fv, remapper); this(Opcodes.ASM6, fv, remapper);
} }
protected FieldRemapper(final int api, final FieldVisitor fv, protected FieldRemapper(final int api, final FieldVisitor fv,

View File

@ -289,7 +289,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
*/ */
public GeneratorAdapter(final MethodVisitor mv, final int access, public GeneratorAdapter(final MethodVisitor mv, final int access,
final String name, final String desc) { final String name, final String desc) {
this(Opcodes.ASM5, mv, access, name, desc); this(Opcodes.ASM6, mv, access, name, desc);
if (getClass() != GeneratorAdapter.class) { if (getClass() != GeneratorAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -300,7 +300,7 @@ public class GeneratorAdapter extends LocalVariablesSorter {
* *
* @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 adapter delegates calls. * the method visitor to which this adapter delegates calls.
* @param access * @param access

View File

@ -86,7 +86,7 @@ public class InstructionAdapter extends MethodVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public InstructionAdapter(final MethodVisitor mv) { public InstructionAdapter(final MethodVisitor mv) {
this(Opcodes.ASM5, mv); this(Opcodes.ASM6, mv);
if (getClass() != InstructionAdapter.class) { if (getClass() != InstructionAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -97,7 +97,7 @@ public class InstructionAdapter extends 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 adapter delegates calls. * the method visitor to which this adapter delegates calls.
*/ */

View File

@ -142,7 +142,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
public JSRInlinerAdapter(final MethodVisitor mv, final int access, public JSRInlinerAdapter(final MethodVisitor mv, final int access,
final String name, final String desc, final String signature, final String name, final String desc, final String signature,
final String[] exceptions) { final String[] exceptions) {
this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
if (getClass() != JSRInlinerAdapter.class) { if (getClass() != JSRInlinerAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -153,7 +153,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes {
* *
* @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 <code>MethodVisitor</code> to send the resulting inlined * the <code>MethodVisitor</code> to send the resulting inlined
* method code to (use <code>null</code> for none). * method code to (use <code>null</code> for none).

View File

@ -120,7 +120,7 @@ public class LocalVariablesSorter extends MethodVisitor {
*/ */
public LocalVariablesSorter(final int access, final String desc, public LocalVariablesSorter(final int access, final String desc,
final MethodVisitor mv) { final MethodVisitor mv) {
this(Opcodes.ASM5, access, desc, mv); this(Opcodes.ASM6, access, desc, mv);
if (getClass() != LocalVariablesSorter.class) { if (getClass() != LocalVariablesSorter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -131,7 +131,7 @@ public class LocalVariablesSorter extends 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 access * @param access
* access flags of the adapted method. * access flags of the adapted method.
* @param desc * @param desc

View File

@ -76,7 +76,7 @@ public class MethodRemapper extends MethodVisitor {
protected final Remapper remapper; protected final Remapper remapper;
public MethodRemapper(final MethodVisitor mv, final Remapper remapper) { public MethodRemapper(final MethodVisitor mv, final Remapper remapper) {
this(Opcodes.ASM5, mv, remapper); this(Opcodes.ASM6, mv, remapper);
} }
protected MethodRemapper(final int api, final MethodVisitor mv, protected MethodRemapper(final int api, final MethodVisitor mv,
@ -122,18 +122,20 @@ public class MethodRemapper extends MethodVisitor {
} }
private Object[] remapEntries(int n, Object[] entries) { private Object[] remapEntries(int n, Object[] entries) {
for (int i = 0; i < n; i++) { if (entries != null) {
if (entries[i] instanceof String) { for (int i = 0; i < n; i++) {
Object[] newEntries = new Object[n]; if (entries[i] instanceof String) {
if (i > 0) { Object[] newEntries = new Object[n];
System.arraycopy(entries, 0, newEntries, 0, i); if (i > 0) {
System.arraycopy(entries, 0, newEntries, 0, i);
}
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
} }
return entries; return entries;

View File

@ -0,0 +1,155 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.commons;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleHashes attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleHashesAttribute extends Attribute {
public String algorithm;
public List<String> modules;
public List<byte[]> hashes;
/**
* Creates an attribute with a hashing algorithm, a list of module names,
* and a list of the same length of hashes.
* @param algorithm the hashing algorithm name.
* @param modules a list of module name
* @param hashes a list of hash, one for each module name.
*/
public ModuleHashesAttribute(final String algorithm,
final List<String> modules, final List<byte[]> hashes) {
super("ModuleHashes");
this.algorithm = algorithm;
this.modules = modules;
this.hashes = hashes;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleHashesAttribute() {
this(null, null, null);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
String hashAlgorithm = cr.readUTF8(off, buf);
int count = cr.readUnsignedShort(off + 2);
ArrayList<String> modules = new ArrayList<String>(count);
ArrayList<byte[]> hashes = new ArrayList<byte[]>(count);
off += 4;
for (int i = 0; i < count; i++) {
String module = cr.readModule(off, buf);
int hashLength = cr.readUnsignedShort(off + 2);
off += 4;
byte[] hash = new byte[hashLength];
for (int j = 0; j < hashLength; j++) {
hash[j] = (byte) (cr.readByte(off + j) & 0xff);
}
off += hashLength;
modules.add(module);
hashes.add(hash);
}
return new ModuleHashesAttribute(hashAlgorithm, modules, hashes);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
int index = cw.newUTF8(algorithm);
v.putShort(index);
int count = (modules == null)? 0: modules.size();
v.putShort(count);
for(int i = 0; i < count; i++) {
String module = modules.get(i);
v.putShort(cw.newModule(module));
byte[] hash = hashes.get(i);
v.putShort(hash.length);
for(byte b: hash) {
v.putByte(b);
}
}
return v;
}
}

View File

@ -0,0 +1,135 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* A {@link ModuleVisitor} adapter for type remapping.
*
* @author Remi Forax
*/
public class ModuleRemapper extends ModuleVisitor {
private final Remapper remapper;
public ModuleRemapper(final ModuleVisitor mv, final Remapper remapper) {
this(Opcodes.ASM6, mv, remapper);
}
protected ModuleRemapper(final int api, final ModuleVisitor mv,
final Remapper remapper) {
super(api, mv);
this.remapper = remapper;
}
@Override
public void visitMainClass(String mainClass) {
super.visitMainClass(remapper.mapType(mainClass));
}
@Override
public void visitPackage(String packaze) {
super.visitPackage(remapper.mapPackageName(packaze));
}
@Override
public void visitRequire(String module, int access, String version) {
super.visitRequire(remapper.mapModuleName(module), access, version);
}
@Override
public void visitExport(String packaze, int access, String... modules) {
String[] newModules = null;
if (modules != null) {
newModules = new String[modules.length];
for (int i = 0 ; i < modules.length; i++) {
newModules[i] = remapper.mapModuleName(modules[i]);
}
}
super.visitExport(remapper.mapPackageName(packaze), access, newModules);
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
String[] newModules = null;
if (modules != null) {
newModules = new String[modules.length];
for (int i = 0 ; i < modules.length; i++) {
newModules[i] = remapper.mapModuleName(modules[i]);
}
}
super.visitOpen(remapper.mapPackageName(packaze), access, newModules);
}
@Override
public void visitUse(String service) {
super.visitUse(remapper.mapType(service));
}
@Override
public void visitProvide(String service, String... providers) {
String[] newProviders = new String[providers.length];
for (int i = 0 ; i < providers.length; i++) {
newProviders[i] = remapper.mapType(providers[i]);
}
super.visitProvide(remapper.mapType(service), newProviders);
}
}

View File

@ -0,0 +1,135 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleResolution_attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleResolutionAttribute extends Attribute {
/**
* Resolution state of a module meaning that the module is not available
* from the class-path by default.
*/
public static final int RESOLUTION_DO_NOT_RESOLVE_BY_DEFAULT = 1;
/**
* Resolution state of a module meaning the module is marked as deprecated.
*/
public static final int RESOLUTION_WARN_DEPRECATED = 2;
/**
* Resolution state of a module meaning the module is marked as deprecated
* and will be removed in a future release.
*/
public static final int RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL = 4;
/**
* Resolution state of a module meaning the module is not yet standardized,
* so in incubating mode.
*/
public static final int RESOLUTION_WARN_INCUBATING = 8;
public int resolution;
/**
* Creates an attribute with a resolution state value.
* @param resolution the resolution state among
* {@link #RESOLUTION_WARN_DEPRECATED},
* {@link #RESOLUTION_WARN_DEPRECATED_FOR_REMOVAL}, and
* {@link #RESOLUTION_WARN_INCUBATING}.
*/
public ModuleResolutionAttribute(final int resolution) {
super("ModuleResolution");
this.resolution = resolution;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleResolutionAttribute() {
this(0);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
int resolution = cr.readUnsignedShort(off);
return new ModuleResolutionAttribute(resolution);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
v.putShort(resolution);
return v;
}
}

View File

@ -0,0 +1,110 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.commons;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ByteVector;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
/**
* ModuleTarget attribute.
* This attribute is specific to the OpenJDK and may change in the future.
*
* @author Remi Forax
*/
public final class ModuleTargetAttribute extends Attribute {
public String platform;
/**
* Creates an attribute with a platform name.
* @param platform the platform name on which the module can run.
*/
public ModuleTargetAttribute(final String platform) {
super("ModuleTarget");
this.platform = platform;
}
/**
* Creates an empty attribute that can be used as prototype
* to be passed as argument of the method
* {@link ClassReader#accept(org.objectweb.asm.ClassVisitor, Attribute[], int)}.
*/
public ModuleTargetAttribute() {
this(null);
}
@Override
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
String platform = cr.readUTF8(off, buf);
return new ModuleTargetAttribute(platform);
}
@Override
protected ByteVector write(ClassWriter cw, byte[] code, int len,
int maxStack, int maxLocals) {
ByteVector v = new ByteVector();
int index = (platform == null)? 0: cw.newUTF8(platform);
v.putShort(index);
return v;
}
}

View File

@ -254,6 +254,28 @@ public abstract class Remapper {
return name; return name;
} }
/**
* Map package name to the new name. Subclasses can override.
*
* @param name name of the package
* @return new name of the package
*/
public String mapPackageName(String name) {
String fakeName = map(name + ".FakeClassName");
int index;
return fakeName == null || (index = fakeName.lastIndexOf('.')) == -1 ? name: fakeName.substring(0, index);
}
/**
* Map module name to the new name. Subclasses can override.
*
* @param name name of the module
* @return new name of the module
*/
public String mapModuleName(String name) {
return name;
}
/** /**
* Map type name to the new name. Subclasses can override. * Map type name to the new name. Subclasses can override.
* *

View File

@ -75,7 +75,7 @@ public class RemappingAnnotationAdapter extends AnnotationVisitor {
public RemappingAnnotationAdapter(final AnnotationVisitor av, public RemappingAnnotationAdapter(final AnnotationVisitor av,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, av, remapper); this(Opcodes.ASM6, av, remapper);
} }
protected RemappingAnnotationAdapter(final int api, protected RemappingAnnotationAdapter(final int api,

View File

@ -63,6 +63,7 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -80,7 +81,7 @@ public class RemappingClassAdapter extends ClassVisitor {
protected String className; protected String className;
public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) { public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
this(Opcodes.ASM5, cv, remapper); this(Opcodes.ASM6, cv, remapper);
} }
protected RemappingClassAdapter(final int api, final ClassVisitor cv, protected RemappingClassAdapter(final int api, final ClassVisitor cv,
@ -98,6 +99,11 @@ public class RemappingClassAdapter extends ClassVisitor {
interfaces == null ? null : remapper.mapTypes(interfaces)); interfaces == null ? null : remapper.mapTypes(interfaces));
} }
@Override
public ModuleVisitor visitModule(String name, int flags, String version) {
throw new RuntimeException("RemappingClassAdapter is deprecated, use ClassRemapper instead");
}
@Override @Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc), AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),

View File

@ -76,7 +76,7 @@ public class RemappingFieldAdapter extends FieldVisitor {
private final Remapper remapper; private final Remapper remapper;
public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) { public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
this(Opcodes.ASM5, fv, remapper); this(Opcodes.ASM6, fv, remapper);
} }
protected RemappingFieldAdapter(final int api, final FieldVisitor fv, protected RemappingFieldAdapter(final int api, final FieldVisitor fv,

View File

@ -79,7 +79,7 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
public RemappingMethodAdapter(final int access, final String desc, public RemappingMethodAdapter(final int access, final String desc,
final MethodVisitor mv, final Remapper remapper) { final MethodVisitor mv, final Remapper remapper) {
this(Opcodes.ASM5, access, desc, mv, remapper); this(Opcodes.ASM6, access, desc, mv, remapper);
} }
protected RemappingMethodAdapter(final int api, final int access, protected RemappingMethodAdapter(final int api, final int access,
@ -125,18 +125,20 @@ public class RemappingMethodAdapter extends LocalVariablesSorter {
} }
private Object[] remapEntries(int n, Object[] entries) { private Object[] remapEntries(int n, Object[] entries) {
for (int i = 0; i < n; i++) { if (entries != null) {
if (entries[i] instanceof String) { for (int i = 0; i < n; i++) {
Object[] newEntries = new Object[n]; if (entries[i] instanceof String) {
if (i > 0) { Object[] newEntries = new Object[n];
System.arraycopy(entries, 0, newEntries, 0, i); if (i > 0) {
System.arraycopy(entries, 0, newEntries, 0, i);
}
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
do {
Object t = entries[i];
newEntries[i++] = t instanceof String ? remapper
.mapType((String) t) : t;
} while (i < n);
return newEntries;
} }
} }
return entries; return entries;

View File

@ -79,7 +79,7 @@ public class RemappingSignatureAdapter extends SignatureVisitor {
public RemappingSignatureAdapter(final SignatureVisitor v, public RemappingSignatureAdapter(final SignatureVisitor v,
final Remapper remapper) { final Remapper remapper) {
this(Opcodes.ASM5, v, remapper); this(Opcodes.ASM6, v, remapper);
} }
protected RemappingSignatureAdapter(final int api, protected RemappingSignatureAdapter(final int api,

View File

@ -80,7 +80,7 @@ import jdk.internal.org.objectweb.asm.Opcodes;
* ClassWriter cw = new ClassWriter(...); * ClassWriter cw = new ClassWriter(...);
* ClassVisitor sv = new SerialVersionUIDAdder(cw); * ClassVisitor sv = new SerialVersionUIDAdder(cw);
* ClassVisitor ca = new MyClassAdapter(sv); * ClassVisitor ca = new MyClassAdapter(sv);
* new ClassReader(originalClass).accept(ca, false); * new ClassReader(orginalClass).accept(ca, false);
* </pre> * </pre>
* *
* The SVUID algorithm can be found <a href= * The SVUID algorithm can be found <a href=
@ -199,7 +199,7 @@ public class SerialVersionUIDAdder extends ClassVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public SerialVersionUIDAdder(final ClassVisitor cv) { public SerialVersionUIDAdder(final ClassVisitor cv) {
this(Opcodes.ASM5, cv); this(Opcodes.ASM6, cv);
if (getClass() != SerialVersionUIDAdder.class) { if (getClass() != SerialVersionUIDAdder.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -210,7 +210,7 @@ public class SerialVersionUIDAdder extends 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
* a {@link ClassVisitor} to which this visitor will delegate * a {@link ClassVisitor} to which this visitor will delegate
* calls. * calls.

View File

@ -78,7 +78,7 @@ public class SignatureRemapper extends SignatureVisitor {
private Stack<String> classNames = new Stack<String>(); private Stack<String> classNames = new Stack<String>();
public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) { public SignatureRemapper(final SignatureVisitor v, final Remapper remapper) {
this(Opcodes.ASM5, v, remapper); this(Opcodes.ASM6, v, remapper);
} }
protected SignatureRemapper(final int api, final SignatureVisitor v, protected SignatureRemapper(final int api, final SignatureVisitor v,

View File

@ -78,7 +78,7 @@ public class StaticInitMerger extends ClassVisitor {
private int counter; private int counter;
public StaticInitMerger(final String prefix, final ClassVisitor cv) { public StaticInitMerger(final String prefix, final ClassVisitor cv) {
this(Opcodes.ASM5, prefix, cv); this(Opcodes.ASM6, prefix, cv);
} }
protected StaticInitMerger(final int api, final String prefix, protected StaticInitMerger(final int api, final String prefix,

View File

@ -86,7 +86,7 @@ public class TryCatchBlockSorter extends MethodNode {
public TryCatchBlockSorter(final MethodVisitor mv, final int access, public TryCatchBlockSorter(final MethodVisitor mv, final int access,
final String name, final String desc, final String signature, final String name, final String desc, final String signature,
final String[] exceptions) { final String[] exceptions) {
this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); this(Opcodes.ASM6, mv, access, name, desc, signature, exceptions);
} }
protected TryCatchBlockSorter(final int api, final MethodVisitor mv, protected TryCatchBlockSorter(final int api, final MethodVisitor mv,

View File

@ -102,7 +102,7 @@ public abstract class SignatureVisitor {
/** /**
* 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;
@ -111,10 +111,10 @@ public abstract class SignatureVisitor {
* *
* @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 SignatureVisitor(final int api) { public SignatureVisitor(final int api) {
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;

View File

@ -95,7 +95,7 @@ public class SignatureWriter extends SignatureVisitor {
* Constructs a new {@link SignatureWriter} object. * Constructs a new {@link SignatureWriter} object.
*/ */
public SignatureWriter() { public SignatureWriter() {
super(Opcodes.ASM5); super(Opcodes.ASM6);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -65,7 +65,7 @@ import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
/** /**
* A node that represents an annotationn. * A node that represents an annotation.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
@ -81,8 +81,8 @@ public class AnnotationNode extends AnnotationVisitor {
* as two consecutive elements in the list. The name is a {@link String}, * as two consecutive elements in the list. The name is a {@link String},
* and the value may be a {@link Byte}, {@link Boolean}, {@link Character}, * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
* {@link Short}, {@link Integer}, {@link Long}, {@link Float}, * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
* {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or an * {@link Double}, {@link String} or {@link jdk.internal.org.objectweb.asm.Type}, or a
* two elements String array (for enumeration values), a * two elements String array (for enumeration values), an
* {@link AnnotationNode}, or a {@link List} of values of one of the * {@link AnnotationNode}, or a {@link List} of values of one of the
* preceding types. The list may be <tt>null</tt> if there is no name value * preceding types. The list may be <tt>null</tt> if there is no name value
* pair. * pair.
@ -100,7 +100,7 @@ public class AnnotationNode extends AnnotationVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public AnnotationNode(final String desc) { public AnnotationNode(final String desc) {
this(Opcodes.ASM5, desc); this(Opcodes.ASM6, desc);
if (getClass() != AnnotationNode.class) { if (getClass() != AnnotationNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -111,7 +111,7 @@ public class AnnotationNode extends 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 desc * @param desc
* the class descriptor of the annotation class. * the class descriptor of the annotation class.
*/ */
@ -127,7 +127,7 @@ public class AnnotationNode extends AnnotationVisitor {
* where the visited values must be stored. * where the visited values must be stored.
*/ */
AnnotationNode(final List<Object> values) { AnnotationNode(final List<Object> values) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
this.values = values; this.values = values;
} }
@ -143,7 +143,65 @@ public class AnnotationNode extends AnnotationVisitor {
if (this.desc != null) { if (this.desc != null) {
values.add(name); values.add(name);
} }
values.add(value); if (value instanceof byte[]) {
byte[] v = (byte[]) value;
ArrayList<Byte> l = new ArrayList<Byte>(v.length);
for (byte b : v) {
l.add(b);
}
values.add(l);
} else if (value instanceof boolean[]) {
boolean[] v = (boolean[]) value;
ArrayList<Boolean> l = new ArrayList<Boolean>(v.length);
for (boolean b : v) {
l.add(b);
}
values.add(l);
} else if (value instanceof short[]) {
short[] v = (short[]) value;
ArrayList<Short> l = new ArrayList<Short>(v.length);
for (short s : v) {
l.add(s);
}
values.add(l);
} else if (value instanceof char[]) {
char[] v = (char[]) value;
ArrayList<Character> l = new ArrayList<Character>(v.length);
for (char c : v) {
l.add(c);
}
values.add(l);
} else if (value instanceof int[]) {
int[] v = (int[]) value;
ArrayList<Integer> l = new ArrayList<Integer>(v.length);
for (int i : v) {
l.add(i);
}
values.add(l);
} else if (value instanceof long[]) {
long[] v = (long[]) value;
ArrayList<Long> l = new ArrayList<Long>(v.length);
for (long lng : v) {
l.add(lng);
}
values.add(l);
} else if (value instanceof float[]) {
float[] v = (float[]) value;
ArrayList<Float> l = new ArrayList<Float>(v.length);
for (float f : v) {
l.add(f);
}
values.add(l);
} else if (value instanceof double[]) {
double[] v = (double[]) value;
ArrayList<Double> l = new ArrayList<Double>(v.length);
for (double d : v) {
l.add(d);
}
values.add(l);
} else {
values.add(value);
}
} }
@Override @Override
@ -200,8 +258,8 @@ public class AnnotationNode extends AnnotationVisitor {
* versions of the ASM API than the given version. * versions of the ASM API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
// nothing to do // nothing to do

View File

@ -67,6 +67,7 @@ import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -126,6 +127,11 @@ public class ClassNode extends ClassVisitor {
*/ */
public String sourceDebug; public String sourceDebug;
/**
* Module information. May be <tt>null</tt>.
*/
public ModuleNode module;
/** /**
* The internal name of the enclosing class of the class. May be * The internal name of the enclosing class of the class. May be
* <tt>null</tt>. * <tt>null</tt>.
@ -221,7 +227,7 @@ public class ClassNode extends ClassVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public ClassNode() { public ClassNode() {
this(Opcodes.ASM5); this(Opcodes.ASM6);
if (getClass() != ClassNode.class) { if (getClass() != ClassNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -232,7 +238,7 @@ public class ClassNode extends 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 ClassNode(final int api) { public ClassNode(final int api) {
super(api); super(api);
@ -266,6 +272,12 @@ public class ClassNode extends ClassVisitor {
sourceDebug = debug; sourceDebug = debug;
} }
@Override
public ModuleVisitor visitModule(final String name, final int access,
final String version) {
return module = new ModuleNode(name, access, version);
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {
@ -358,11 +370,16 @@ public class ClassNode extends ClassVisitor {
* API than the given version. * API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api < Opcodes.ASM6) {
if (module != null) {
throw new RuntimeException();
}
}
if (api < Opcodes.ASM5) {
if (visibleTypeAnnotations != null if (visibleTypeAnnotations != null
&& visibleTypeAnnotations.size() > 0) { && visibleTypeAnnotations.size() > 0) {
throw new RuntimeException(); throw new RuntimeException();
@ -371,12 +388,31 @@ public class ClassNode extends ClassVisitor {
&& invisibleTypeAnnotations.size() > 0) { && invisibleTypeAnnotations.size() > 0) {
throw new RuntimeException(); throw new RuntimeException();
} }
for (FieldNode f : fields) { }
f.check(api); // checks attributes
} int i, n;
for (MethodNode m : methods) { n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
m.check(api); for (i = 0; i < n; ++i) {
} visibleAnnotations.get(i).check(api);
}
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
for (i = 0; i < n; ++i) {
invisibleAnnotations.get(i).check(api);
}
n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
for (i = 0; i < n; ++i) {
visibleTypeAnnotations.get(i).check(api);
}
n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
.size();
for (i = 0; i < n; ++i) {
invisibleTypeAnnotations.get(i).check(api);
}
for (FieldNode f : fields) {
f.check(api);
}
for (MethodNode m : methods) {
m.check(api);
} }
} }
@ -395,6 +431,10 @@ public class ClassNode extends ClassVisitor {
if (sourceFile != null || sourceDebug != null) { if (sourceFile != null || sourceDebug != null) {
cv.visitSource(sourceFile, sourceDebug); cv.visitSource(sourceFile, sourceDebug);
} }
// visits module
if (module != null) {
module.accept(cv);
}
// visits outer class // visits outer class
if (outerClass != null) { if (outerClass != null) {
cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc); cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);

View File

@ -173,7 +173,7 @@ public class FieldNode extends FieldVisitor {
*/ */
public FieldNode(final int access, final String name, final String desc, public FieldNode(final int access, final String name, final String desc,
final String signature, final Object value) { final String signature, final Object value) {
this(Opcodes.ASM5, access, name, desc, signature, value); this(Opcodes.ASM6, access, name, desc, signature, value);
if (getClass() != FieldNode.class) { if (getClass() != FieldNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -276,8 +276,8 @@ public class FieldNode extends FieldVisitor {
* API than the given version. * API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api == Opcodes.ASM4) {

View File

@ -634,14 +634,28 @@ public class InsnList {
} }
public void add(Object o) { public void add(Object o) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o); if (next != null) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
} else if (prev != null) {
InsnList.this.insert(prev, (AbstractInsnNode) o);
} else {
InsnList.this.add((AbstractInsnNode) o);
}
prev = (AbstractInsnNode) o; prev = (AbstractInsnNode) o;
remove = null; remove = null;
} }
public void set(Object o) { public void set(Object o) {
InsnList.this.set(next.prev, (AbstractInsnNode) o); if (remove != null) {
prev = (AbstractInsnNode) o; InsnList.this.set(remove, (AbstractInsnNode) o);
if (remove == prev) {
prev = (AbstractInsnNode) o;
} else {
next = (AbstractInsnNode) o;
}
} else {
throw new IllegalStateException();
}
} }
} }
} }

View File

@ -122,7 +122,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
*/ */
public LocalVariableAnnotationNode(int typeRef, TypePath typePath, public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
LabelNode[] start, LabelNode[] end, int[] index, String desc) { LabelNode[] start, LabelNode[] end, int[] index, String desc) {
this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc); this(Opcodes.ASM6, typeRef, typePath, start, end, index, desc);
} }
/** /**
@ -130,7 +130,7 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
* *
* @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 typeRef * @param typeRef
* a reference to the annotated type. See {@link TypeReference}. * a reference to the annotated type. See {@link TypeReference}.
* @param start * @param start
@ -181,6 +181,6 @@ public class LocalVariableAnnotationNode extends TypeAnnotationNode {
index[i] = this.index.get(i); index[i] = this.index.get(i);
} }
accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end, accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
index, desc, true)); index, desc, visible));
} }
} }

View File

@ -249,7 +249,7 @@ public class MethodNode extends MethodVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public MethodNode() { public MethodNode() {
this(Opcodes.ASM5); this(Opcodes.ASM6);
if (getClass() != MethodNode.class) { if (getClass() != MethodNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -260,7 +260,7 @@ public class MethodNode extends 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 MethodNode(final int api) { public MethodNode(final int api) {
super(api); super(api);
@ -291,7 +291,7 @@ public class MethodNode extends MethodVisitor {
*/ */
public MethodNode(final int access, final String name, final String desc, public MethodNode(final int access, final String name, final String desc,
final String signature, final String[] exceptions) { final String signature, final String[] exceptions) {
this(Opcodes.ASM5, access, name, desc, signature, exceptions); this(Opcodes.ASM6, access, name, desc, signature, exceptions);
if (getClass() != MethodNode.class) { if (getClass() != MethodNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -302,7 +302,7 @@ public class MethodNode extends 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 access * @param access
* the method's access flags (see {@link Opcodes}). This * the method's access flags (see {@link Opcodes}). This
* parameter also indicates if the method is synthetic and/or * parameter also indicates if the method is synthetic and/or
@ -688,8 +688,8 @@ public class MethodNode extends MethodVisitor {
* versions of the ASM API than the given version. * versions of the ASM API than the given version.
* *
* @param api * @param api
* an ASM API version. Must be one of {@link Opcodes#ASM4} or * an ASM API version. Must be one of {@link Opcodes#ASM4},
* {@link Opcodes#ASM5}. * {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
public void check(final int api) { public void check(final int api) {
if (api == Opcodes.ASM4) { if (api == Opcodes.ASM4) {

View File

@ -0,0 +1,111 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents an exported package with its name and the module that can access to it.
*
* @author Remi Forax
*/
public class ModuleExportNode {
/**
* The package name.
*/
public String packaze;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
*/
public int access;
/**
* A list of modules that can access to this exported package.
* May be <tt>null</tt>.
*/
public List<String> modules;
/**
* Constructs a new {@link ModuleExportNode}.
*
* @param packaze
* the parameter's name.
* @param modules
* a list of modules that can access to this exported package.
*/
public ModuleExportNode(final String packaze, final int access, final List<String> modules) {
this.packaze = packaze;
this.access = access;
this.modules = modules;
}
/**
* Makes the given module visitor visit this export declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
}
}

View File

@ -0,0 +1,280 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.tree;
import java.util.ArrayList;
import java.util.List;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* A node that represents a module declaration.
*
* @author Remi Forax
*/
public class ModuleNode extends ModuleVisitor {
/**
* Module name
*/
public String name;
/**
* Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
* and {@code ACC_MANDATED}.
*/
public int access;
/**
* Version of the module.
* May be <tt>null</tt>.
*/
public String version;
/**
* Name of the main class in internal form
* May be <tt>null</tt>.
*/
public String mainClass;
/**
* A list of packages that are declared by the current module.
* May be <tt>null</tt>.
*/
public List<String> packages;
/**
* A list of modules can are required by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleRequireNode> requires;
/**
* A list of packages that are exported by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleExportNode> exports;
/**
* A list of packages that are opened by the current module.
* May be <tt>null</tt>.
*/
public List<ModuleOpenNode> opens;
/**
* A list of classes in their internal forms that are used
* as a service by the current module. May be <tt>null</tt>.
*/
public List<String> uses;
/**
* A list of services along with their implementations provided
* by the current module. May be <tt>null</tt>.
*/
public List<ModuleProvideNode> provides;
public ModuleNode(final String name, final int access,
final String version) {
super(Opcodes.ASM6);
this.name = name;
this.access = access;
this.version = version;
}
public ModuleNode(final int api,
final String name,
final int access,
final String version,
final List<ModuleRequireNode> requires,
final List<ModuleExportNode> exports,
final List<ModuleOpenNode> opens,
final List<String> uses,
final List<ModuleProvideNode> provides) {
super(api);
this.name = name;
this.access = access;
this.version = version;
this.requires = requires;
this.exports = exports;
this.opens = opens;
this.uses = uses;
this.provides = provides;
if (getClass() != ModuleNode.class) {
throw new IllegalStateException();
}
}
@Override
public void visitMainClass(String mainClass) {
this.mainClass = mainClass;
}
@Override
public void visitPackage(String packaze) {
if (packages == null) {
packages = new ArrayList<String>(5);
}
packages.add(packaze);
}
@Override
public void visitRequire(String module, int access, String version) {
if (requires == null) {
requires = new ArrayList<ModuleRequireNode>(5);
}
requires.add(new ModuleRequireNode(module, access, version));
}
@Override
public void visitExport(String packaze, int access, String... modules) {
if (exports == null) {
exports = new ArrayList<ModuleExportNode>(5);
}
List<String> moduleList = null;
if (modules != null) {
moduleList = new ArrayList<String>(modules.length);
for (int i = 0; i < modules.length; i++) {
moduleList.add(modules[i]);
}
}
exports.add(new ModuleExportNode(packaze, access, moduleList));
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
if (opens == null) {
opens = new ArrayList<ModuleOpenNode>(5);
}
List<String> moduleList = null;
if (modules != null) {
moduleList = new ArrayList<String>(modules.length);
for (int i = 0; i < modules.length; i++) {
moduleList.add(modules[i]);
}
}
opens.add(new ModuleOpenNode(packaze, access, moduleList));
}
@Override
public void visitUse(String service) {
if (uses == null) {
uses = new ArrayList<String>(5);
}
uses.add(service);
}
@Override
public void visitProvide(String service, String... providers) {
if (provides == null) {
provides = new ArrayList<ModuleProvideNode>(5);
}
ArrayList<String> providerList =
new ArrayList<String>(providers.length);
for (int i = 0; i < providers.length; i++) {
providerList.add(providers[i]);
}
provides.add(new ModuleProvideNode(service, providerList));
}
@Override
public void visitEnd() {
}
public void accept(final ClassVisitor cv) {
ModuleVisitor mv = cv.visitModule(name, access, version);
if (mv == null) {
return;
}
if (mainClass != null) {
mv.visitMainClass(mainClass);
}
if (packages != null) {
for (int i = 0; i < packages.size(); i++) {
mv.visitPackage(packages.get(i));
}
}
if (requires != null) {
for (int i = 0; i < requires.size(); i++) {
requires.get(i).accept(mv);
}
}
if (exports != null) {
for (int i = 0; i < exports.size(); i++) {
exports.get(i).accept(mv);
}
}
if (opens != null) {
for (int i = 0; i < opens.size(); i++) {
opens.get(i).accept(mv);
}
}
if (uses != null) {
for (int i = 0; i < uses.size(); i++) {
mv.visitUse(uses.get(i));
}
}
if (provides != null) {
for (int i = 0; i < provides.size(); i++) {
provides.get(i).accept(mv);
}
}
}
}

View File

@ -0,0 +1,111 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents an opened package with its name and the module that can access to it.
*
* @author Remi Forax
*/
public class ModuleOpenNode {
/**
* The package name.
*/
public String packaze;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
*/
public int access;
/**
* A list of modules that can access to this exported package.
* May be <tt>null</tt>.
*/
public List<String> modules;
/**
* Constructs a new {@link ModuleOpenNode}.
*
* @param packaze
* the parameter's name.
* @param modules
* a list of modules that can access to this open package.
*/
public ModuleOpenNode(final String packaze, final int access, final List<String> modules) {
this.packaze = packaze;
this.access = access;
this.modules = modules;
}
/**
* Makes the given module visitor visit this open declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitExport(packaze, access, (modules == null) ? null : modules.toArray(new String[0]));
}
}

View File

@ -0,0 +1,103 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.tree;
import java.util.List;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents a service and its implementation provided by the current module.
*
* @author Remi Forax
*/
public class ModuleProvideNode {
/**
* The service name (in its internal form).
*/
public String service;
/**
* The service provider names (in their internal form).
*/
public List<String> providers;
/**
* Constructs a new {@link ModuleProvideNode}.
*
* @param service
* the service name (in its internal form).
* @param providers
* the service provider names (in their internal form).
*/
public ModuleProvideNode(final String service, final List<String> providers) {
this.service = service;
this.providers = providers;
}
/**
* Makes the given module visitor visit this require declaration.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitProvide(service, providers.toArray(new String[0]));
}
}

View File

@ -0,0 +1,116 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.tree;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
/**
* A node that represents a required module with its name and access of a module descriptor.
*
* @author Remi Forax
*/
public class ModuleRequireNode {
/**
* The name of the required module.
*/
public String module;
/**
* The access flags (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* Valid values are <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>.
*/
public int access;
/**
* Version at compile time of the required module or null.
*/
public String version;
/**
* Constructs a new {@link ModuleRequireNode}.
*
* @param module
* the name of the required module.
* @param access
* The access flags. Valid values are
* <tt>ACC_TRANSITIVE</tt>, <tt>ACC_STATIC_PHASE</tt>,
* <tt>ACC_SYNTHETIC</tt> and <tt>ACC_MANDATED</tt>
* (see {@link jdk.internal.org.objectweb.asm.Opcodes}).
* @param version
* Version of the required module at compile time,
* null if not defined.
*/
public ModuleRequireNode(final String module, final int access,
final String version) {
this.module = module;
this.access = access;
this.version = version;
}
/**
* Makes the given module visitor visit this require directive.
*
* @param mv
* a module visitor.
*/
public void accept(final ModuleVisitor mv) {
mv.visitRequire(module, access, version);
}
}

View File

@ -99,7 +99,7 @@ public class TypeAnnotationNode extends AnnotationNode {
*/ */
public TypeAnnotationNode(final int typeRef, final TypePath typePath, public TypeAnnotationNode(final int typeRef, final TypePath typePath,
final String desc) { final String desc) {
this(Opcodes.ASM5, typeRef, typePath, desc); this(Opcodes.ASM6, typeRef, typePath, desc);
if (getClass() != TypeAnnotationNode.class) { if (getClass() != TypeAnnotationNode.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -110,7 +110,7 @@ public class TypeAnnotationNode extends AnnotationNode {
* *
* @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 typeRef * @param typeRef
* a reference to the annotated type. See {@link TypeReference}. * a reference to the annotated type. See {@link TypeReference}.
* @param typePath * @param typePath

View File

@ -82,7 +82,7 @@ public class BasicInterpreter extends Interpreter<BasicValue> implements
Opcodes { Opcodes {
public BasicInterpreter() { public BasicInterpreter() {
super(ASM5); super(ASM6);
} }
protected BasicInterpreter(final int api) { protected BasicInterpreter(final int api) {

View File

@ -76,7 +76,7 @@ import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
public class BasicVerifier extends BasicInterpreter { public class BasicVerifier extends BasicInterpreter {
public BasicVerifier() { public BasicVerifier() {
super(ASM5); super(ASM6);
} }
protected BasicVerifier(final int api) { protected BasicVerifier(final int api) {

View File

@ -136,7 +136,7 @@ public class SimpleVerifier extends BasicVerifier {
public SimpleVerifier(final Type currentClass, public SimpleVerifier(final Type currentClass,
final Type currentSuperClass, final Type currentSuperClass,
final List<Type> currentClassInterfaces, final boolean isInterface) { final List<Type> currentClassInterfaces, final boolean isInterface) {
this(ASM5, currentClass, currentSuperClass, currentClassInterfaces, this(ASM6, currentClass, currentSuperClass, currentClassInterfaces,
isInterface); isInterface);
} }

View File

@ -79,7 +79,7 @@ public class SourceInterpreter extends Interpreter<SourceValue> implements
Opcodes { Opcodes {
public SourceInterpreter() { public SourceInterpreter() {
super(ASM5); super(ASM6);
} }
protected SourceInterpreter(final int api) { protected SourceInterpreter(final int api) {

View File

@ -109,6 +109,11 @@ public class ASMifier extends Printer {
*/ */
private static final int ACCESS_INNER = 1048576; private static final int ACCESS_INNER = 1048576;
/**
* Pseudo access flag used to distinguish module requires/exports flags.
*/
private static final int ACCESS_MODULE = 2097152;
/** /**
* Constructs a new {@link ASMifier}. <i>Subclasses must not use this * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the * constructor</i>. Instead, they must use the
@ -118,7 +123,7 @@ public class ASMifier extends Printer {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public ASMifier() { public ASMifier() {
this(Opcodes.ASM5, "cw", 0); this(Opcodes.ASM6, "cw", 0);
if (getClass() != ASMifier.class) { if (getClass() != ASMifier.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -129,7 +134,7 @@ public class ASMifier extends Printer {
* *
* @param api * @param api
* the ASM API version implemented by this class. Must be one of * the ASM API version implemented by this class. Must be one of
* {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
* @param name * @param name
* the name of the visitor variable in the produced code. * the name of the visitor variable in the produced code.
* @param id * @param id
@ -196,13 +201,17 @@ public class ASMifier extends Printer {
final String signature, final String superName, final String signature, final String superName,
final String[] interfaces) { final String[] interfaces) {
String simpleName; String simpleName;
int n = name.lastIndexOf('/'); if (name == null) {
if (n == -1) { simpleName = "module-info";
simpleName = name;
} else { } else {
text.add("package asm." + name.substring(0, n).replace('/', '.') int n = name.lastIndexOf('/');
+ ";\n"); if (n == -1) {
simpleName = name.substring(n + 1); simpleName = name;
} else {
text.add("package asm." + name.substring(0, n).replace('/', '.')
+ ";\n");
simpleName = name.substring(n + 1).replace('-', '_');
}
} }
text.add("import java.util.*;\n"); text.add("import java.util.*;\n");
text.add("import jdk.internal.org.objectweb.asm.*;\n"); text.add("import jdk.internal.org.objectweb.asm.*;\n");
@ -237,6 +246,12 @@ public class ASMifier extends Printer {
case Opcodes.V1_7: case Opcodes.V1_7:
buf.append("V1_7"); buf.append("V1_7");
break; break;
case Opcodes.V1_8:
buf.append("V1_8");
break;
case Opcodes.V9:
buf.append("V9");
break;
default: default:
buf.append(version); buf.append(version);
break; break;
@ -275,6 +290,24 @@ public class ASMifier extends Printer {
text.add(buf.toString()); text.add(buf.toString());
} }
@Override
public Printer visitModule(final String name, final int flags,
final String version) {
buf.setLength(0);
buf.append("ModuleVisitor mdv = cw.visitModule(");
appendConstant(name);
buf.append(", ");
appendAccess(flags | ACCESS_MODULE);
buf.append(", ");
appendConstant(version);
buf.append(");\n\n");
text.add(buf.toString());
ASMifier a = createASMifier("mdv", 0);
text.add(a.getText());
text.add("}\n");
return a;
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {
@ -385,6 +418,108 @@ public class ASMifier extends Printer {
text.add("}\n"); text.add("}\n");
} }
// ------------------------------------------------------------------------
// Module
// ------------------------------------------------------------------------
@Override
public void visitMainClass(String mainClass) {
buf.setLength(0);
buf.append("mdv.visitMainClass(");
appendConstant(buf, mainClass);
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitPackage(String packaze) {
buf.setLength(0);
buf.append("mdv.visitPackage(");
appendConstant(buf, packaze);
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitRequire(String module, int access, String version) {
buf.setLength(0);
buf.append("mdv.visitRequire(");
appendConstant(buf, module);
buf.append(", ");
appendAccess(access | ACCESS_MODULE);
buf.append(", ");
appendConstant(buf, version);
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitExport(String packaze, int access, String... modules) {
buf.setLength(0);
buf.append("mdv.visitExport(");
appendConstant(buf, packaze);
buf.append(", ");
appendAccess(access | ACCESS_MODULE);
if (modules != null && modules.length > 0) {
buf.append(", new String[] {");
for (int i = 0; i < modules.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(modules[i]);
}
buf.append(" }");
}
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
buf.setLength(0);
buf.append("mdv.visitOpen(");
appendConstant(buf, packaze);
buf.append(", ");
appendAccess(access | ACCESS_MODULE);
if (modules != null && modules.length > 0) {
buf.append(", new String[] {");
for (int i = 0; i < modules.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(modules[i]);
}
buf.append(" }");
}
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitUse(String service) {
buf.setLength(0);
buf.append("mdv.visitUse(");
appendConstant(buf, service);
buf.append(");\n");
text.add(buf.toString());
}
@Override
public void visitProvide(String service, String... providers) {
buf.setLength(0);
buf.append("mdv.visitProvide(");
appendConstant(buf, service);
buf.append(", new String[] {");
for (int i = 0; i < providers.length; ++i) {
buf.append(i == 0 ? " " : ", ");
appendConstant(providers[i]);
}
buf.append(" });\n");
text.add(buf.toString());
}
@Override
public void visitModuleEnd() {
text.add("mdv.visitEnd();\n");
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Annotations // Annotations
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -972,7 +1107,7 @@ public class ASMifier extends Printer {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
protected ASMifier createASMifier(final String name, final int id) { protected ASMifier createASMifier(final String name, final int id) {
return new ASMifier(Opcodes.ASM5, name, id); return new ASMifier(Opcodes.ASM6, name, id);
} }
/** /**
@ -1000,7 +1135,11 @@ public class ASMifier extends Printer {
if (!first) { if (!first) {
buf.append(" + "); buf.append(" + ");
} }
buf.append("ACC_FINAL"); if ((access & ACCESS_MODULE) == 0) {
buf.append("ACC_FINAL");
} else {
buf.append("ACC_TRANSITIVE");
}
first = false; first = false;
} }
if ((access & Opcodes.ACC_STATIC) != 0) { if ((access & Opcodes.ACC_STATIC) != 0) {
@ -1010,31 +1149,35 @@ public class ASMifier extends Printer {
buf.append("ACC_STATIC"); buf.append("ACC_STATIC");
first = false; first = false;
} }
if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) { if ((access & (Opcodes.ACC_SYNCHRONIZED | Opcodes.ACC_SUPER | Opcodes.ACC_TRANSITIVE)) != 0) {
if (!first) { if (!first) {
buf.append(" + "); buf.append(" + ");
} }
if ((access & ACCESS_CLASS) == 0) { if ((access & ACCESS_CLASS) == 0) {
buf.append("ACC_SYNCHRONIZED"); if ((access & ACCESS_MODULE) == 0) {
buf.append("ACC_SYNCHRONIZED");
} else {
buf.append("ACC_TRANSITIVE");
}
} else { } else {
buf.append("ACC_SUPER"); buf.append("ACC_SUPER");
} }
first = false; first = false;
} }
if ((access & Opcodes.ACC_VOLATILE) != 0 if ((access & (Opcodes.ACC_VOLATILE | Opcodes.ACC_BRIDGE | Opcodes.ACC_STATIC_PHASE)) != 0) {
&& (access & ACCESS_FIELD) != 0) {
if (!first) { if (!first) {
buf.append(" + "); buf.append(" + ");
} }
buf.append("ACC_VOLATILE"); if ((access & ACCESS_FIELD) == 0) {
first = false; if ((access & ACCESS_MODULE) == 0) {
} buf.append("ACC_BRIDGE");
if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0 } else {
&& (access & ACCESS_FIELD) == 0) { buf.append("ACC_STATIC_PHASE");
if (!first) { }
buf.append(" + "); } else {
buf.append("ACC_VOLATILE");
} }
buf.append("ACC_BRIDGE");
first = false; first = false;
} }
if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0 if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
@ -1113,11 +1256,15 @@ public class ASMifier extends Printer {
buf.append("ACC_DEPRECATED"); buf.append("ACC_DEPRECATED");
first = false; first = false;
} }
if ((access & Opcodes.ACC_MANDATED) != 0) { if ((access & (Opcodes.ACC_MANDATED | Opcodes.ACC_MODULE)) != 0) {
if (!first) { if (!first) {
buf.append(" + "); buf.append(" + ");
} }
buf.append("ACC_MANDATED"); if ((access & ACCESS_CLASS) == 0) {
buf.append("ACC_MANDATED");
} else {
buf.append("ACC_MODULE");
}
first = false; first = false;
} }
if (first) { if (first) {
@ -1163,7 +1310,8 @@ public class ASMifier extends Printer {
.append(", \""); .append(", \"");
buf.append(h.getOwner()).append("\", \""); buf.append(h.getOwner()).append("\", \"");
buf.append(h.getName()).append("\", \""); buf.append(h.getName()).append("\", \"");
buf.append(h.getDesc()).append("\")"); buf.append(h.getDesc()).append("\", ");
buf.append(h.isInterface()).append(")");
} else if (cst instanceof Byte) { } else if (cst instanceof Byte) {
buf.append("new Byte((byte)").append(cst).append(')'); buf.append("new Byte((byte)").append(cst).append(')');
} else if (cst instanceof Boolean) { } else if (cst instanceof Boolean) {

View File

@ -78,7 +78,7 @@ public class CheckAnnotationAdapter extends AnnotationVisitor {
} }
CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) { CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
super(Opcodes.ASM5, av); super(Opcodes.ASM6, av);
this.named = named; this.named = named;
} }

View File

@ -73,6 +73,7 @@ import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.Label; import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.Type;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -180,6 +181,11 @@ public class CheckClassAdapter extends ClassVisitor {
*/ */
private boolean end; private boolean end;
/**
* <tt>true</tt> if the visitModule method has been called.
*/
private boolean module;
/** /**
* The already visited labels. This map associate Integer values to Label * The already visited labels. This map associate Integer values to Label
* keys. * keys.
@ -363,7 +369,7 @@ public class CheckClassAdapter extends ClassVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
this(Opcodes.ASM5, cv, checkDataFlow); this(Opcodes.ASM6, cv, checkDataFlow);
if (getClass() != CheckClassAdapter.class) { if (getClass() != CheckClassAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -374,7 +380,7 @@ public class CheckClassAdapter extends 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 adapter must delegate calls. * the class visitor to which this adapter must delegate calls.
* @param checkDataFlow * @param checkDataFlow
@ -407,8 +413,12 @@ public class CheckClassAdapter extends ClassVisitor {
+ Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + Opcodes.ACC_DEPRECATED + Opcodes.ACC_MODULE
if (name == null || !name.endsWith("package-info")) { + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
if (name == null) {
throw new IllegalArgumentException("Illegal class name (null)");
}
if (!name.endsWith("package-info")) {
CheckMethodAdapter.checkInternalName(name, "class name"); CheckMethodAdapter.checkInternalName(name, "class name");
} }
if ("java/lang/Object".equals(name)) { if ("java/lang/Object".equals(name)) {
@ -449,6 +459,22 @@ public class CheckClassAdapter extends ClassVisitor {
super.visitSource(file, debug); super.visitSource(file, debug);
} }
@Override
public ModuleVisitor visitModule(String name, int access, String version) {
checkState();
if (module) {
throw new IllegalStateException(
"visitModule can be called only once.");
}
module = true;
if (name == null) {
throw new IllegalArgumentException("Illegal module name (null)");
}
checkAccess(access, Opcodes.ACC_OPEN | Opcodes.ACC_SYNTHETIC);
return new CheckModuleAdapter(super.visitModule(name, access, version),
(access & Opcodes.ACC_OPEN) != 0);
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {

View File

@ -83,7 +83,7 @@ public class CheckFieldAdapter extends FieldVisitor {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public CheckFieldAdapter(final FieldVisitor fv) { public CheckFieldAdapter(final FieldVisitor fv) {
this(Opcodes.ASM5, fv); this(Opcodes.ASM6, fv);
if (getClass() != CheckFieldAdapter.class) { if (getClass() != CheckFieldAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -94,7 +94,7 @@ public class CheckFieldAdapter extends 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 adapter must delegate calls. * the field visitor to which this adapter must delegate calls.
*/ */

View File

@ -426,7 +426,7 @@ public class CheckMethodAdapter extends MethodVisitor {
*/ */
public CheckMethodAdapter(final MethodVisitor mv, public CheckMethodAdapter(final MethodVisitor mv,
final Map<Label, Integer> labels) { final Map<Label, Integer> labels) {
this(Opcodes.ASM5, mv, labels); this(Opcodes.ASM6, mv, labels);
if (getClass() != CheckMethodAdapter.class) { if (getClass() != CheckMethodAdapter.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -439,7 +439,8 @@ public class CheckMethodAdapter extends MethodVisitor {
* *
* @param api * @param api
* the ASM API version implemented by this CheckMethodAdapter. * the ASM API version implemented by this CheckMethodAdapter.
* 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}.
* @param mv * @param mv
* the method visitor to which this adapter must delegate calls. * the method visitor to which this adapter must delegate calls.
* @param labels * @param labels
@ -756,6 +757,12 @@ public class CheckMethodAdapter extends MethodVisitor {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"INVOKEINTERFACE can't be used with classes"); "INVOKEINTERFACE can't be used with classes");
} }
if (opcode == Opcodes.INVOKESPECIAL && itf
&& (version & 0xFFFF) < Opcodes.V1_8) {
throw new IllegalArgumentException(
"INVOKESPECIAL can't be used with interfaces prior to Java 8");
}
// Calling super.visitMethodInsn requires to call the correct version // Calling super.visitMethodInsn requires to call the correct version
// depending on this.api (otherwise infinite loops can occur). To // depending on this.api (otherwise infinite loops can occur). To
// simplify and to make it easier to automatically remove the backward // simplify and to make it easier to automatically remove the backward

View File

@ -0,0 +1,180 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.util;
import java.util.HashSet;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* @author Remi Forax
*/
public final class CheckModuleAdapter extends ModuleVisitor {
private boolean end;
private final boolean isOpen;
private final HashSet<String> requireNames = new HashSet<String>();
private final HashSet<String> exportNames = new HashSet<String>();
private final HashSet<String> openNames = new HashSet<String>();
private final HashSet<String> useNames = new HashSet<String>();
private final HashSet<String> provideNames = new HashSet<String>();
public CheckModuleAdapter(final ModuleVisitor mv, final boolean isOpen) {
super(Opcodes.ASM6, mv);
this.isOpen = isOpen;
}
@Override
public void visitRequire(String module, int access, String version) {
checkEnd();
if (module == null) {
throw new IllegalArgumentException("require cannot be null");
}
checkDeclared("requires", requireNames, module);
CheckClassAdapter.checkAccess(access, Opcodes.ACC_STATIC_PHASE
+ Opcodes.ACC_TRANSITIVE + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_MANDATED);
super.visitRequire(module, access, version);
}
@Override
public void visitExport(String packaze, int access, String... modules) {
checkEnd();
if (packaze == null) {
throw new IllegalArgumentException("packaze cannot be null");
}
CheckMethodAdapter.checkInternalName(packaze, "package name");
checkDeclared("exports", exportNames, packaze);
CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
+ Opcodes.ACC_MANDATED);
if (modules != null) {
for (int i = 0; i < modules.length; i++) {
if (modules[i] == null) {
throw new IllegalArgumentException("module at index " + i + " cannot be null");
}
}
}
super.visitExport(packaze, access, modules);
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
checkEnd();
if (isOpen) {
throw new IllegalArgumentException("an open module can not use open directive");
}
if (packaze == null) {
throw new IllegalArgumentException("packaze cannot be null");
}
CheckMethodAdapter.checkInternalName(packaze, "package name");
checkDeclared("opens", openNames, packaze);
CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC
+ Opcodes.ACC_MANDATED);
if (modules != null) {
for (int i = 0; i < modules.length; i++) {
if (modules[i] == null) {
throw new IllegalArgumentException("module at index " + i + " cannot be null");
}
}
}
super.visitOpen(packaze, access, modules);
}
@Override
public void visitUse(String service) {
checkEnd();
CheckMethodAdapter.checkInternalName(service, "service");
checkDeclared("uses", useNames, service);
super.visitUse(service);
}
@Override
public void visitProvide(String service, String... providers) {
checkEnd();
CheckMethodAdapter.checkInternalName(service, "service");
checkDeclared("provides", provideNames, service);
if (providers == null || providers.length == 0) {
throw new IllegalArgumentException("providers cannot be null or empty");
}
for (int i = 0; i < providers.length; i++) {
CheckMethodAdapter.checkInternalName(providers[i], "provider");
}
super.visitProvide(service, providers);
}
@Override
public void visitEnd() {
checkEnd();
end = true;
super.visitEnd();
}
private void checkEnd() {
if (end) {
throw new IllegalStateException(
"Cannot call a visit method after visitEnd has been called");
}
}
private static void checkDeclared(String directive, HashSet<String> names, String name) {
if (!names.add(name)) {
throw new IllegalArgumentException(directive + " " + name + " already declared");
}
}
}

View File

@ -142,7 +142,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
* <tt>null</tt>. * <tt>null</tt>.
*/ */
public CheckSignatureAdapter(final int type, final SignatureVisitor sv) { public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
this(Opcodes.ASM5, type, sv); this(Opcodes.ASM6, type, sv);
} }
/** /**
@ -150,7 +150,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
* *
* @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 type * @param type
* the type of signature to be checked. See * the type of signature to be checked. See
* {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
@ -175,7 +175,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
|| (state != EMPTY && state != FORMAL && state != BOUND)) { || (state != EMPTY && state != FORMAL && state != BOUND)) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
CheckMethodAdapter.checkIdentifier(name, "formal type parameter"); checkIdentifier(name, "formal type parameter");
state = FORMAL; state = FORMAL;
if (sv != null) { if (sv != null) {
sv.visitFormalTypeParameter(name); sv.visitFormalTypeParameter(name);
@ -284,7 +284,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
if (type != TYPE_SIGNATURE || state != EMPTY) { if (type != TYPE_SIGNATURE || state != EMPTY) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
CheckMethodAdapter.checkIdentifier(name, "type variable"); checkIdentifier(name, "type variable");
state = SIMPLE_TYPE; state = SIMPLE_TYPE;
if (sv != null) { if (sv != null) {
sv.visitTypeVariable(name); sv.visitTypeVariable(name);
@ -306,7 +306,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
if (type != TYPE_SIGNATURE || state != EMPTY) { if (type != TYPE_SIGNATURE || state != EMPTY) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
CheckMethodAdapter.checkInternalName(name, "class name"); checkClassName(name, "class name");
state = CLASS_TYPE; state = CLASS_TYPE;
if (sv != null) { if (sv != null) {
sv.visitClassType(name); sv.visitClassType(name);
@ -318,7 +318,7 @@ public class CheckSignatureAdapter extends SignatureVisitor {
if (state != CLASS_TYPE) { if (state != CLASS_TYPE) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
CheckMethodAdapter.checkIdentifier(name, "inner class name"); checkIdentifier(name, "inner class name");
if (sv != null) { if (sv != null) {
sv.visitInnerClassType(name); sv.visitInnerClassType(name);
} }
@ -356,4 +356,30 @@ public class CheckSignatureAdapter extends SignatureVisitor {
sv.visitEnd(); sv.visitEnd();
} }
} }
private void checkClassName(final String name, final String msg) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Invalid " + msg
+ " (must not be null or empty)");
}
for (int i = 0; i < name.length(); ++i) {
if (".;[<>:".indexOf(name.charAt(i)) != -1) {
throw new IllegalArgumentException("Invalid " + msg
+ " (must not contain . ; [ < > or :): " + name);
}
}
}
private void checkIdentifier(final String name, final String msg) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Invalid " + msg
+ " (must not be null or empty)");
}
for (int i = 0; i < name.length(); ++i) {
if (".;[/<>:".indexOf(name.charAt(i)) != -1) {
throw new IllegalArgumentException("Invalid " + msg
+ " (must not contain . ; [ / < > or :): " + name);
}
}
}
} }

View File

@ -146,7 +146,7 @@ public abstract class Printer {
/** /**
* The ASM API version implemented by this class. The value of this field * The ASM API version implemented by this class. 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;
@ -174,7 +174,7 @@ public abstract class Printer {
* *
* @param api * @param api
* the ASM API version implemented by this printer. Must be one * the ASM API version implemented by this printer. Must be one
* of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}. * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
*/ */
protected Printer(final int api) { protected Printer(final int api) {
this.api = api; this.api = api;
@ -226,6 +226,24 @@ public abstract class Printer {
*/ */
public abstract void visitSource(final String source, final String debug); public abstract void visitSource(final String source, final String debug);
/**
* Module.
* See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitModule(String, int)}.
*
* @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
*/
public Printer visitModule(String name, int access, String version) {
throw new RuntimeException("Must be overriden");
}
/** /**
* Class outer class. * Class outer class.
* See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}. * See {@link jdk.internal.org.objectweb.asm.ClassVisitor#visitOuterClass}.
@ -375,6 +393,45 @@ public abstract class Printer {
*/ */
public abstract void visitClassEnd(); public abstract void visitClassEnd();
// ------------------------------------------------------------------------
// Module
// ------------------------------------------------------------------------
public void visitMainClass(String mainClass) {
throw new RuntimeException("Must be overriden");
}
public void visitPackage(String packaze) {
throw new RuntimeException("Must be overriden");
}
public void visitRequire(String module, int access, String version) {
throw new RuntimeException("Must be overriden");
}
public void visitExport(String packaze, int access, String... modules) {
throw new RuntimeException("Must be overriden");
}
public void visitOpen(String packaze, int access, String... modules) {
throw new RuntimeException("Must be overriden");
}
public void visitUse(String service) {
throw new RuntimeException("Must be overriden");
}
public void visitProvide(String service, String... providers) {
throw new RuntimeException("Must be overriden");
}
/**
* Module end. See {@link jdk.internal.org.objectweb.asm.ModuleVisitor#visitEnd}.
*/
public void visitModuleEnd() {
throw new RuntimeException("Must be overriden");
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Annotations // Annotations
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -182,7 +182,7 @@ public class Textifier extends Printer {
* If a subclass calls this constructor. * If a subclass calls this constructor.
*/ */
public Textifier() { public Textifier() {
this(Opcodes.ASM5); this(Opcodes.ASM6);
if (getClass() != Textifier.class) { if (getClass() != Textifier.class) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -193,7 +193,7 @@ public class Textifier extends Printer {
* *
* @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}.
*/ */
protected Textifier(final int api) { protected Textifier(final int api) {
super(api); super(api);
@ -250,6 +250,10 @@ public class Textifier extends Printer {
public void visit(final int version, final int access, final String name, public void visit(final int version, final int access, final String name,
final String signature, final String superName, final String signature, final String superName,
final String[] interfaces) { final String[] interfaces) {
if ((access & Opcodes.ACC_MODULE) != 0) {
// visitModule will print the module
return;
}
this.access = access; this.access = access;
int major = version & 0xFFFF; int major = version & 0xFFFF;
int minor = version >>> 16; int minor = version >>> 16;
@ -271,7 +275,7 @@ public class Textifier extends Printer {
.append(sv.getDeclaration()).append('\n'); .append(sv.getDeclaration()).append('\n');
} }
appendAccess(access & ~Opcodes.ACC_SUPER); appendAccess(access & ~(Opcodes.ACC_SUPER | Opcodes.ACC_MODULE));
if ((access & Opcodes.ACC_ANNOTATION) != 0) { if ((access & Opcodes.ACC_ANNOTATION) != 0) {
buf.append("@interface "); buf.append("@interface ");
} else if ((access & Opcodes.ACC_INTERFACE) != 0) { } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
@ -314,6 +318,24 @@ public class Textifier extends Printer {
} }
} }
@Override
public Printer visitModule(final String name, final int access,
final String version) {
buf.setLength(0);
if ((access & Opcodes.ACC_OPEN) != 0) {
buf.append("open ");
}
buf.append("module ")
.append(name)
.append(" { ")
.append(version == null ? "" : "// " + version)
.append("\n\n");
text.add(buf.toString());
Textifier t = createTextifier();
text.add(t.getText());
return t;
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {
@ -443,7 +465,7 @@ public class Textifier extends Printer {
} }
buf.append(tab); buf.append(tab);
appendAccess(access & ~Opcodes.ACC_VOLATILE); appendAccess(access & ~(Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT));
if ((access & Opcodes.ACC_NATIVE) != 0) { if ((access & Opcodes.ACC_NATIVE) != 0) {
buf.append("native "); buf.append("native ");
} }
@ -482,6 +504,118 @@ public class Textifier extends Printer {
text.add("}\n"); text.add("}\n");
} }
// ------------------------------------------------------------------------
// Module
// ------------------------------------------------------------------------
@Override
public void visitMainClass(String mainClass) {
buf.setLength(0);
buf.append(" // main class ").append(mainClass).append('\n');
text.add(buf.toString());
}
@Override
public void visitPackage(String packaze) {
buf.setLength(0);
buf.append(" // package ").append(packaze).append('\n');
text.add(buf.toString());
}
@Override
public void visitRequire(String require, int access, String version) {
buf.setLength(0);
buf.append(tab).append("requires ");
if ((access & Opcodes.ACC_TRANSITIVE) != 0) {
buf.append("transitive ");
}
if ((access & Opcodes.ACC_STATIC_PHASE) != 0) {
buf.append("static ");
}
buf.append(require)
.append("; // access flags 0x")
.append(Integer.toHexString(access).toUpperCase())
.append('\n');
if (version != null) {
buf.append(" // version ")
.append(version)
.append('\n');
}
text.add(buf.toString());
}
@Override
public void visitExport(String export, int access, String... modules) {
buf.setLength(0);
buf.append(tab).append("exports ");
buf.append(export);
if (modules != null && modules.length > 0) {
buf.append(" to");
} else {
buf.append(';');
}
buf.append(" // access flags 0x")
.append(Integer.toHexString(access).toUpperCase())
.append('\n');
if (modules != null && modules.length > 0) {
for (int i = 0; i < modules.length; ++i) {
buf.append(tab2).append(modules[i]);
buf.append(i != modules.length - 1 ? ",\n": ";\n");
}
}
text.add(buf.toString());
}
@Override
public void visitOpen(String export, int access, String... modules) {
buf.setLength(0);
buf.append(tab).append("opens ");
buf.append(export);
if (modules != null && modules.length > 0) {
buf.append(" to");
} else {
buf.append(';');
}
buf.append(" // access flags 0x")
.append(Integer.toHexString(access).toUpperCase())
.append('\n');
if (modules != null && modules.length > 0) {
for (int i = 0; i < modules.length; ++i) {
buf.append(tab2).append(modules[i]);
buf.append(i != modules.length - 1 ? ",\n": ";\n");
}
}
text.add(buf.toString());
}
@Override
public void visitUse(String use) {
buf.setLength(0);
buf.append(tab).append("uses ");
appendDescriptor(INTERNAL_NAME, use);
buf.append(";\n");
text.add(buf.toString());
}
@Override
public void visitProvide(String provide, String... providers) {
buf.setLength(0);
buf.append(tab).append("provides ");
appendDescriptor(INTERNAL_NAME, provide);
buf.append(" with\n");
for (int i = 0; i < providers.length; ++i) {
buf.append(tab2);
appendDescriptor(INTERNAL_NAME, providers[i]);
buf.append(i != providers.length - 1 ? ",\n": ";\n");
}
text.add(buf.toString());
}
@Override
public void visitModuleEnd() {
// empty
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Annotations // Annotations
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -1296,13 +1430,16 @@ public class Textifier extends Printer {
appendDescriptor(INTERNAL_NAME, h.getOwner()); appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.'); buf.append('.');
buf.append(h.getName()); buf.append(h.getName());
if(!isMethodHandle){ if (!isMethodHandle) {
buf.append('('); buf.append('(');
} }
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc()); appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
if(!isMethodHandle){ if (!isMethodHandle) {
buf.append(')'); buf.append(')');
} }
if (h.isInterface()) {
buf.append(" itf");
}
} }
/** /**

View File

@ -76,7 +76,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor {
} }
public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) { public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
super(Opcodes.ASM5, av); super(Opcodes.ASM6, av);
this.p = p; this.p = p;
} }

View File

@ -65,6 +65,7 @@ import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor; import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.TypePath; import jdk.internal.org.objectweb.asm.TypePath;
@ -160,7 +161,7 @@ public final class TraceClassVisitor extends ClassVisitor {
*/ */
public TraceClassVisitor(final ClassVisitor cv, final Printer p, public TraceClassVisitor(final ClassVisitor cv, final Printer p,
final PrintWriter pw) { final PrintWriter pw) {
super(Opcodes.ASM5, cv); super(Opcodes.ASM6, cv);
this.pw = pw; this.pw = pw;
this.p = p; this.p = p;
} }
@ -179,6 +180,14 @@ public final class TraceClassVisitor extends ClassVisitor {
super.visitSource(file, debug); super.visitSource(file, debug);
} }
@Override
public ModuleVisitor visitModule(String name, int flags,
String version) {
Printer p = this.p.visitModule(name, flags, version);
ModuleVisitor mv = super.visitModule(name, flags, version);
return new TraceModuleVisitor(mv, p);
}
@Override @Override
public void visitOuterClass(final String owner, final String name, public void visitOuterClass(final String owner, final String name,
final String desc) { final String desc) {

View File

@ -79,7 +79,7 @@ public final class TraceFieldVisitor extends FieldVisitor {
} }
public TraceFieldVisitor(final FieldVisitor fv, final Printer p) { public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
super(Opcodes.ASM5, fv); super(Opcodes.ASM6, fv);
this.p = p; this.p = p;
} }

View File

@ -81,7 +81,7 @@ public final class TraceMethodVisitor extends MethodVisitor {
} }
public TraceMethodVisitor(final MethodVisitor mv, final Printer p) { public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
super(Opcodes.ASM5, mv); super(Opcodes.ASM6, mv);
this.p = p; this.p = p;
} }

View File

@ -0,0 +1,130 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* 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 jdk.internal.org.objectweb.asm.util;
import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
/**
* A {@link ModuleVisitor} that prints the fields it visits with a
* {@link Printer}.
*
* @author Remi Forax
*/
public final class TraceModuleVisitor extends ModuleVisitor {
public final Printer p;
public TraceModuleVisitor(final Printer p) {
this(null, p);
}
public TraceModuleVisitor(final ModuleVisitor mv, final Printer p) {
super(Opcodes.ASM6, mv);
this.p = p;
}
@Override
public void visitMainClass(String mainClass) {
p.visitMainClass(mainClass);
super.visitMainClass(mainClass);
}
@Override
public void visitPackage(String packaze) {
p.visitPackage(packaze);
super.visitPackage(packaze);
}
@Override
public void visitRequire(String module, int access, String version) {
p.visitRequire(module, access, version);
super.visitRequire(module, access, version);
}
@Override
public void visitExport(String packaze, int access, String... modules) {
p.visitExport(packaze, access, modules);
super.visitExport(packaze, access, modules);
}
@Override
public void visitOpen(String packaze, int access, String... modules) {
p.visitOpen(packaze, access, modules);
super.visitOpen(packaze, access, modules);
}
@Override
public void visitUse(String use) {
p.visitUse(use);
super.visitUse(use);
}
@Override
public void visitProvide(String service, String... providers) {
p.visitProvide(service, providers);
super.visitProvide(service, providers);
}
@Override
public void visitEnd() {
p.visitModuleEnd();
super.visitEnd();
}
}

View File

@ -104,13 +104,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor {
private String separator = ""; private String separator = "";
public TraceSignatureVisitor(final int access) { public TraceSignatureVisitor(final int access) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0; isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
this.declaration = new StringBuilder(); this.declaration = new StringBuilder();
} }
private TraceSignatureVisitor(final StringBuilder buf) { private TraceSignatureVisitor(final StringBuilder buf) {
super(Opcodes.ASM5); super(Opcodes.ASM6);
this.declaration = buf; this.declaration = buf;
} }

View File

@ -1,12 +1,4 @@
Path: . ASM_6_0-11-gac81f5f
Working Copy Root Path: /hudson/jobs/objectweb-init/workspace/asm-svn-2016-01-25 origin https://gitlab.ow2.org/asm/asm.git (fetch)
URL: file:///svnroot/asm/trunk/asm ac81f5f Merge branch 'add-class-dump-tool-for-unit-tests' into 'master'
Repository Root: file:///svnroot/asm
Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9
Revision: 1795
Node Kind: directory
Schedule: normal
Last Changed Author: ebruneton
Last Changed Rev: 1795
Last Changed Date: 2016-01-24 14:17:10 +0100 (Sun, 24 Jan 2016)

View File

@ -47,13 +47,13 @@ public class ConstModule {
// Test that the JVM throws CFE for constant pool CONSTANT_Module type, for // Test that the JVM throws CFE for constant pool CONSTANT_Module type, for
// class file version 53, when ACC_MODULE is not set in the access_flags. // class file version 53, when ACC_MODULE is not set in the access_flags.
ConstModule.write_and_load(Opcodes.V1_9, ConstModule.write_and_load(Opcodes.V9,
Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC,
"jdk.fooMod", "FooMod", MODULE_TEST, CFE_EXCEPTION); "jdk.fooMod", "FooMod", MODULE_TEST, CFE_EXCEPTION);
// Test that the JVM throws NCDFE for constant pool CONSTANT_Module type, // Test that the JVM throws NCDFE for constant pool CONSTANT_Module type,
// for class file version 53, when ACC_MODULE is set in the access_flags. // for class file version 53, when ACC_MODULE is set in the access_flags.
ConstModule.write_and_load(Opcodes.V1_9, ConstModule.write_and_load(Opcodes.V9,
Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
"jdk.fooModACC", "FooModACC", MODULE_TEST, NCDFE_EXCEPTION); "jdk.fooModACC", "FooModACC", MODULE_TEST, NCDFE_EXCEPTION);
@ -65,13 +65,13 @@ public class ConstModule {
// Test that the JVM throws CFE for constant pool CONSTANT_Package type, for // Test that the JVM throws CFE for constant pool CONSTANT_Package type, for
// class file version 53, when ACC_MODULE is not set in the access_flags. // class file version 53, when ACC_MODULE is not set in the access_flags.
ConstModule.write_and_load(Opcodes.V1_9, ConstModule.write_and_load(Opcodes.V9,
Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC,
"jdk.fooPkg", "FooPkg", PACKAGE_TEST, CFE_EXCEPTION); "jdk.fooPkg", "FooPkg", PACKAGE_TEST, CFE_EXCEPTION);
// Test that the JVM throws NCDFE for constant pool CONSTANT_Package type, // Test that the JVM throws NCDFE for constant pool CONSTANT_Package type,
// for class file version 53, when ACC_MODULE is set in the access_flags. // for class file version 53, when ACC_MODULE is set in the access_flags.
ConstModule.write_and_load(Opcodes.V1_9, ConstModule.write_and_load(Opcodes.V9,
Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC + ACC_MODULE,
"jdk.fooModACC", "FooModACC", PACKAGE_TEST, NCDFE_EXCEPTION); "jdk.fooModACC", "FooModACC", PACKAGE_TEST, NCDFE_EXCEPTION);

View File

@ -34,13 +34,13 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import jdk.internal.module.ClassFileAttributes;
import jdk.internal.org.objectweb.asm.AnnotationVisitor; import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import static org.testng.Assert.*; import static org.testng.Assert.*;
@ -48,6 +48,7 @@ import static org.testng.Assert.*;
/** /**
* @test * @test
* @modules java.base/jdk.internal.org.objectweb.asm * @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.org.objectweb.asm.commons
* java.base/jdk.internal.module * java.base/jdk.internal.module
* java.xml * java.xml
* @run testng AnnotationsTest * @run testng AnnotationsTest
@ -113,14 +114,11 @@ public class AnnotationsTest {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) { }; ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) { };
ClassReader cr = new ClassReader(in); ClassReader cr = new ClassReader(in);
List<Attribute> attrs = new ArrayList<>(); List<Attribute> attrs = new ArrayList<>();
attrs.add(new ClassFileAttributes.ModuleAttribute()); attrs.add(new ModuleTargetAttribute());
attrs.add(new ClassFileAttributes.ModulePackagesAttribute());
attrs.add(new ClassFileAttributes.ModuleTargetAttribute());
cr.accept(cv, attrs.toArray(new Attribute[0]), 0); cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
AnnotationVisitor annotationVisitor AnnotationVisitor annotationVisitor

View File

@ -243,7 +243,7 @@ public class DefineClassTest {
byte[] generateClass(String className) { byte[] generateClass(String className) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_9, cw.visit(V9,
ACC_PUBLIC + ACC_SUPER, ACC_PUBLIC + ACC_SUPER,
className.replace(".", "/"), className.replace(".", "/"),
null, null,
@ -272,7 +272,7 @@ public class DefineClassTest {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_9, cw.visit(V9,
ACC_PUBLIC + ACC_SUPER, ACC_PUBLIC + ACC_SUPER,
className.replace(".", "/"), className.replace(".", "/"),
null, null,
@ -309,7 +309,7 @@ public class DefineClassTest {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_9, cw.visit(V9,
ACC_PUBLIC + ACC_SUPER, ACC_PUBLIC + ACC_SUPER,
className.replace(".", "/"), className.replace(".", "/"),
null, null,

View File

@ -209,7 +209,7 @@ public class BadProvidersTest {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES); + ClassWriter.COMPUTE_FRAMES);
cw.visit(V1_9, cw.visit(V9,
ACC_PUBLIC + ACC_SUPER, ACC_PUBLIC + ACC_SUPER,
"p/ProviderFactory", "p/ProviderFactory",
null, null,

View File

@ -29,13 +29,9 @@ import java.net.URI;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import jdk.internal.module.ClassFileConstants;
import jdk.internal.module.ClassFileAttributes; import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
public class ModuleTargetHelper { public class ModuleTargetHelper {
private ModuleTargetHelper() {} private ModuleTargetHelper() {}
@ -60,29 +56,12 @@ public class ModuleTargetHelper {
} }
public static ModuleTarget read(InputStream in) throws IOException { public static ModuleTarget read(InputStream in) throws IOException {
ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { if (attrs.target() != null) {
@Override return new ModuleTarget(attrs.target().targetPlatform());
public void visitAttribute(Attribute attr) { } else {
if (attr instanceof ModuleTargetAttribute) { return null;
modTargets[0] = (ModuleTargetAttribute)attr;
}
}
};
// prototype of attributes that should be parsed
Attribute[] attrs = new Attribute[] {
new ModuleTargetAttribute()
};
// parse module-info.class
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
if (modTargets[0] != null) {
return new ModuleTarget(modTargets[0].targetPlatform());
} }
return null;
} }
public static ModuleTarget read(ModuleReference modRef) throws IOException { public static ModuleTarget read(ModuleReference modRef) throws IOException {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,35 +34,13 @@ import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import jdk.internal.module.ClassFileAttributes; import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.module.ClassFileConstants;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
public class Main { public class Main {
private static boolean hasModuleTarget(InputStream in) throws IOException { private static boolean hasModuleTarget(InputStream in) throws IOException {
ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { return attrs.target() != null;
@Override
public void visitAttribute(Attribute attr) {
if (attr instanceof ModuleTargetAttribute) {
modTargets[0] = (ModuleTargetAttribute)attr;
}
}
};
// prototype of attributes that should be parsed
Attribute[] attrs = new Attribute[] {
new ModuleTargetAttribute()
};
// parse module-info.class
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
return modTargets[0] != null && modTargets[0].targetPlatform() != null;
} }
public static void main(String... args) throws Exception { public static void main(String... args) throws Exception {

View File

@ -35,35 +35,13 @@ import java.nio.file.Path;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jdk.internal.module.ClassFileAttributes; import jdk.internal.module.ModuleInfo;
import jdk.internal.module.ClassFileAttributes.ModuleTargetAttribute; import jdk.internal.module.ModuleInfo.Attributes;
import jdk.internal.module.ClassFileConstants;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
public class Main { public class Main {
private static boolean hasModuleTarget(InputStream in) throws IOException { private static boolean hasModuleTarget(InputStream in) throws IOException {
ModuleTargetAttribute[] modTargets = new ModuleTargetAttribute[1]; ModuleInfo.Attributes attrs = ModuleInfo.read(in, null);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) { return attrs.target() != null;
@Override
public void visitAttribute(Attribute attr) {
if (attr instanceof ModuleTargetAttribute) {
modTargets[0] = (ModuleTargetAttribute)attr;
}
}
};
// prototype of attributes that should be parsed
Attribute[] attrs = new Attribute[] {
new ModuleTargetAttribute()
};
// parse module-info.class
ClassReader cr = new ClassReader(in);
cr.accept(cv, attrs, 0);
return modTargets[0] != null && modTargets[0].targetPlatform() != null;
} }
private static boolean hasModuleTarget(String modName) throws IOException { private static boolean hasModuleTarget(String modName) throws IOException {