Mercurial > hg > release > icedtea7-forest-2.3 > langtools
changeset 435:4b3ebc896806
Merge
author | andrew |
---|---|
date | Sun, 01 Nov 2009 15:21:14 +0000 |
parents | 27f109855e7f (current diff) 2485f5641ed0 (diff) |
children | 83367f01297b |
files | src/share/classes/com/sun/tools/javac/jvm/ClassReader.java |
diffstat | 23 files changed, 1270 insertions(+), 155 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Mon Oct 19 13:38:09 2009 -0700 +++ b/.hgtags Sun Nov 01 15:21:14 2009 +0000 @@ -48,3 +48,4 @@ 33c8c38e1757006c17d80499fb3347102501fae5 jdk7-b71 261c54b2312ed26d6ec45c675831375460250519 jdk7-b72 9596dff460935f09684c11d156ce591f92584f0d jdk7-b73 +1a66b08deed0459054b5b1bea3dfbead30d258fa jdk7-b74
--- a/src/share/classes/com/sun/tools/classfile/ConstantPool.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/classfile/ConstantPool.java Sun Nov 01 15:21:14 2009 +0000 @@ -369,14 +369,33 @@ return 3; } + /** + * Get the raw value of the class referenced by this constant pool entry. + * This will either be the name of the class, in internal form, or a + * descriptor for an array class. + * @return the raw value of the class + */ public String getName() throws ConstantPoolException { return cp.getUTF8Value(name_index); } + /** + * If this constant pool entry identifies either a class or interface type, + * or a possibly multi-dimensional array of a class of interface type, + * return the name of the class or interface in internal form. Otherwise, + * (i.e. if this is a possibly multi-dimensional array of a primitive type), + * return null. + * @return the base class or interface name + */ public String getBaseName() throws ConstantPoolException { String name = getName(); - int index = name.indexOf("[L") + 1; - return name.substring(index); + if (name.startsWith("[")) { + int index = name.indexOf("[L"); + if (index == -1) + return null; + return name.substring(index + 2, name.length() - 1); + } else + return name; } public int getDimensionCount() throws ConstantPoolException {
--- a/src/share/classes/com/sun/tools/classfile/Signature.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/classfile/Signature.java Sun Nov 01 15:21:14 2009 +0000 @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import com.sun.tools.classfile.Type.*; /** * See JVMS3 4.4.4. @@ -50,19 +51,19 @@ @Override public int getParameterCount(ConstantPool constant_pool) throws ConstantPoolException { - Type.MethodType m = (Type.MethodType) getType(constant_pool); - return m.argTypes.size(); + MethodType m = (MethodType) getType(constant_pool); + return m.paramTypes.size(); } @Override public String getParameterTypes(ConstantPool constant_pool) throws ConstantPoolException { - Type.MethodType m = (Type.MethodType) getType(constant_pool); + MethodType m = (MethodType) getType(constant_pool); StringBuilder sb = new StringBuilder(); sb.append("("); String sep = ""; - for (Type argType: m.argTypes) { + for (Type paramType: m.paramTypes) { sb.append(sep); - sb.append(argType); + sb.append(paramType); sep = ", "; } sb.append(")"); @@ -71,7 +72,7 @@ @Override public String getReturnType(ConstantPool constant_pool) throws ConstantPoolException { - Type.MethodType m = (Type.MethodType) getType(constant_pool); + MethodType m = (MethodType) getType(constant_pool); return m.returnType.toString(); } @@ -84,12 +85,12 @@ this.sig = sig; sigp = 0; - List<Type> typeArgTypes = null; + List<TypeParamType> typeParamTypes = null; if (sig.charAt(sigp) == '<') - typeArgTypes = parseTypeArgTypes(); + typeParamTypes = parseTypeParamTypes(); if (sig.charAt(sigp) == '(') { - List<Type> argTypes = parseTypeSignatures(')'); + List<Type> paramTypes = parseTypeSignatures(')'); Type returnType = parseTypeSignature(); List<Type> throwsTypes = null; while (sigp < sig.length() && sig.charAt(sigp) == '^') { @@ -98,16 +99,19 @@ throwsTypes = new ArrayList<Type>(); throwsTypes.add(parseTypeSignature()); } - return new Type.MethodType(typeArgTypes, argTypes, returnType, throwsTypes); + return new MethodType(typeParamTypes, paramTypes, returnType, throwsTypes); } else { Type t = parseTypeSignature(); - if (typeArgTypes == null && sigp == sig.length()) + if (typeParamTypes == null && sigp == sig.length()) return t; Type superclass = t; - List<Type> superinterfaces = new ArrayList<Type>(); - while (sigp < sig.length()) + List<Type> superinterfaces = null; + while (sigp < sig.length()) { + if (superinterfaces == null) + superinterfaces = new ArrayList<Type>(); superinterfaces.add(parseTypeSignature()); - return new Type.ClassSigType(typeArgTypes, superclass, superinterfaces); + } + return new ClassSigType(typeParamTypes, superclass, superinterfaces); } } @@ -116,61 +120,61 @@ switch (sig.charAt(sigp)) { case 'B': sigp++; - return new Type.SimpleType("byte"); + return new SimpleType("byte"); case 'C': sigp++; - return new Type.SimpleType("char"); + return new SimpleType("char"); case 'D': sigp++; - return new Type.SimpleType("double"); + return new SimpleType("double"); case 'F': sigp++; - return new Type.SimpleType("float"); + return new SimpleType("float"); case 'I': sigp++; - return new Type.SimpleType("int"); + return new SimpleType("int"); case 'J': sigp++; - return new Type.SimpleType("long"); + return new SimpleType("long"); case 'L': return parseClassTypeSignature(); case 'S': sigp++; - return new Type.SimpleType("short"); + return new SimpleType("short"); case 'T': return parseTypeVariableSignature(); case 'V': sigp++; - return new Type.SimpleType("void"); + return new SimpleType("void"); case 'Z': sigp++; - return new Type.SimpleType("boolean"); + return new SimpleType("boolean"); case '[': sigp++; - return new Type.ArrayType(parseTypeSignature()); + return new ArrayType(parseTypeSignature()); case '*': sigp++; - return new Type.WildcardType(); + return new WildcardType(); case '+': sigp++; - return new Type.WildcardType("extends", parseTypeSignature()); + return new WildcardType(WildcardType.Kind.EXTENDS, parseTypeSignature()); case '-': sigp++; - return new Type.WildcardType("super", parseTypeSignature()); + return new WildcardType(WildcardType.Kind.SUPER, parseTypeSignature()); default: throw new IllegalStateException(debugInfo()); @@ -194,30 +198,22 @@ private Type parseClassTypeSignatureRest() { StringBuilder sb = new StringBuilder(); - Type t = null; - char sigch; - while (true) { + List<Type> argTypes = null; + ClassType t = null; + char sigch ; + + do { switch (sigch = sig.charAt(sigp)) { - case '/': - sigp++; - sb.append("."); + case '<': + argTypes = parseTypeSignatures('>'); break; case '.': - sigp++; - if (t == null) - t = new Type.SimpleType(sb.toString()); - return new Type.InnerClassType(t, parseClassTypeSignatureRest()); - case ';': sigp++; - if (t == null) - t = new Type.SimpleType(sb.toString()); - return t; - - case '<': - List<Type> argTypes = parseTypeSignatures('>'); - t = new Type.ClassType(sb.toString(), argTypes); + t = new ClassType(t, sb.toString(), argTypes); + sb.setLength(0); + argTypes = null; break; default: @@ -225,21 +221,22 @@ sb.append(sigch); break; } - } + } while (sigch != ';'); + + return t; } - private List<Type> parseTypeArgTypes() { + private List<TypeParamType> parseTypeParamTypes() { assert sig.charAt(sigp) == '<'; sigp++; - List<Type> types = null; - types = new ArrayList<Type>(); + List<TypeParamType> types = new ArrayList<TypeParamType>(); while (sig.charAt(sigp) != '>') - types.add(parseTypeArgType()); + types.add(parseTypeParamType()); sigp++; return types; } - private Type parseTypeArgType() { + private TypeParamType parseTypeParamType() { int sep = sig.indexOf(":", sigp); String name = sig.substring(sigp, sep); Type classBound = null; @@ -253,13 +250,13 @@ interfaceBounds = new ArrayList<Type>(); interfaceBounds.add(parseTypeSignature()); } - return new Type.TypeArgType(name, classBound, interfaceBounds); + return new TypeParamType(name, classBound, interfaceBounds); } private Type parseTypeVariableSignature() { sigp++; int sep = sig.indexOf(';', sigp); - Type t = new Type.SimpleType(sig.substring(sigp, sep)); + Type t = new SimpleType(sig.substring(sigp, sep)); sigp = sep + 1; return t; }
--- a/src/share/classes/com/sun/tools/classfile/Type.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/classfile/Type.java Sun Nov 01 15:21:14 2009 +0000 @@ -31,6 +31,9 @@ import java.util.Set; /* + * Family of classes used to represent the parsed form of a {@link Descriptor} + * or {@link Signature}. + * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or @@ -62,11 +65,26 @@ R visitMethodType(MethodType type, P p); R visitClassSigType(ClassSigType type, P p); R visitClassType(ClassType type, P p); - R visitInnerClassType(InnerClassType type, P p); - R visitTypeArgType(TypeArgType type, P p); + R visitTypeParamType(TypeParamType type, P p); R visitWildcardType(WildcardType type, P p); } + /** + * Represents a type signature with a simple name. The name may be that of a + * primitive type, such "{@code int}, {@code float}, etc + * or that of a type argument, such as {@code T}, {@code K}, {@code V}, etc. + * + * See: + * JVMS 4.3.2 + * BaseType: + * {@code B}, {@code C}, {@code D}, {@code F}, {@code I}, + * {@code J}, {@code S}, {@code Z}; + * VoidDescriptor: + * {@code V}; + * JVMS 4.3.4 + * TypeVariableSignature: + * {@code T} Identifier {@code ;} + */ public static class SimpleType extends Type { public SimpleType(String name) { this.name = name; @@ -91,6 +109,14 @@ public final String name; } + /** + * Represents an array type signature. + * + * See: + * JVMS 4.3.4 + * ArrayTypeSignature: + * {@code [} TypeSignature {@code ]} + */ public static class ArrayType extends Type { public ArrayType(Type elemType) { this.elemType = elemType; @@ -108,17 +134,26 @@ public final Type elemType; } + /** + * Represents a method type signature. + * + * See; + * JVMS 4.3.4 + * MethodTypeSignature: + * FormalTypeParameters_opt {@code (} TypeSignature* {@code)} ReturnType + * ThrowsSignature* + */ public static class MethodType extends Type { - public MethodType(List<? extends Type> argTypes, Type resultType) { - this(null, argTypes, resultType, null); + public MethodType(List<? extends Type> paramTypes, Type resultType) { + this(null, paramTypes, resultType, null); } - public MethodType(List<? extends Type> typeArgTypes, - List<? extends Type> argTypes, + public MethodType(List<? extends TypeParamType> typeParamTypes, + List<? extends Type> paramTypes, Type returnType, List<? extends Type> throwsTypes) { - this.typeArgTypes = typeArgTypes; - this.argTypes = argTypes; + this.typeParamTypes = typeParamTypes; + this.paramTypes = paramTypes; this.returnType = returnType; this.throwsTypes = throwsTypes; } @@ -130,22 +165,32 @@ @Override public String toString() { StringBuilder sb = new StringBuilder(); - appendIfNotEmpty(sb, "<", typeArgTypes, "> "); + appendIfNotEmpty(sb, "<", typeParamTypes, "> "); sb.append(returnType); - append(sb, " (", argTypes, ")"); + append(sb, " (", paramTypes, ")"); appendIfNotEmpty(sb, " throws ", throwsTypes, ""); return sb.toString(); } - public final List<? extends Type> typeArgTypes; - public final List<? extends Type> argTypes; + public final List<? extends TypeParamType> typeParamTypes; + public final List<? extends Type> paramTypes; public final Type returnType; public final List<? extends Type> throwsTypes; } + /** + * Represents a class signature. These describe the signature of + * a class that has type arguments. + * + * See: + * JVMS 4.3.4 + * ClassSignature: + * FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature* + */ public static class ClassSigType extends Type { - public ClassSigType(List<Type> typeArgTypes, Type superclassType, List<Type> superinterfaceTypes) { - this.typeArgTypes = typeArgTypes; + public ClassSigType(List<TypeParamType> typeParamTypes, Type superclassType, + List<Type> superinterfaceTypes) { + this.typeParamTypes = typeParamTypes; this.superclassType = superclassType; this.superinterfaceTypes = superinterfaceTypes; } @@ -157,7 +202,7 @@ @Override public String toString() { StringBuilder sb = new StringBuilder(); - appendIfNotEmpty(sb, "<", typeArgTypes, ">"); + appendIfNotEmpty(sb, "<", typeParamTypes, ">"); if (superclassType != null) { sb.append(" extends "); sb.append(superclassType); @@ -166,13 +211,30 @@ return sb.toString(); } - public final List<Type> typeArgTypes; + public final List<TypeParamType> typeParamTypes; public final Type superclassType; public final List<Type> superinterfaceTypes; } + /** + * Represents a class type signature. This is used to represent a + * reference to a class, such as in a field, parameter, return type, etc. + * + * See: + * JVMS 4.3.4 + * ClassTypeSignature: + * {@code L} PackageSpecifier_opt SimpleClassTypeSignature + * ClassTypeSignatureSuffix* {@code ;} + * PackageSpecifier: + * Identifier {@code /} PackageSpecifier* + * SimpleClassTypeSignature: + * Identifier TypeArguments_opt } + * ClassTypeSignatureSuffix: + * {@code .} SimpleClassTypeSignature + */ public static class ClassType extends Type { - public ClassType(String name, List<Type> typeArgs) { + public ClassType(ClassType outerType, String name, List<Type> typeArgs) { + this.outerType = outerType; this.name = name; this.typeArgs = typeArgs; } @@ -181,47 +243,54 @@ return visitor.visitClassType(this, data); } + public String getBinaryName() { + if (outerType == null) + return name; + else + return (outerType.getBinaryName() + "$" + name); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); + if (outerType != null) { + sb.append(outerType); + sb.append("."); + } sb.append(name); appendIfNotEmpty(sb, "<", typeArgs, ">"); return sb.toString(); } + public final ClassType outerType; public final String name; public final List<Type> typeArgs; } - - public static class InnerClassType extends Type { - public InnerClassType(Type outerType, Type innerType) { - this.outerType = outerType; - this.innerType = innerType; - } - - public <R, D> R accept(Visitor<R, D> visitor, D data) { - return visitor.visitInnerClassType(this, data); - } - - @Override - public String toString() { - return outerType + "." + innerType; - } - - public final Type outerType; - public final Type innerType; - } - - public static class TypeArgType extends Type { - public TypeArgType(String name, Type classBound, List<Type> interfaceBounds) { + /** + * Represents a FormalTypeParameter. These are used to declare the type + * parameters for generic classes and methods. + * + * See: + * JVMS 4.3.4 + * FormalTypeParameters: + * {@code <} FormalTypeParameter+ {@code >} + * FormalTypeParameter: + * Identifier ClassBound InterfaceBound* + * ClassBound: + * {@code :} FieldTypeSignature_opt + * InterfaceBound: + * {@code :} FieldTypeSignature + */ + public static class TypeParamType extends Type { + public TypeParamType(String name, Type classBound, List<Type> interfaceBounds) { this.name = name; this.classBound = classBound; this.interfaceBounds = interfaceBounds; } public <R, D> R accept(Visitor<R, D> visitor, D data) { - return visitor.visitTypeArgType(this, data); + return visitor.visitTypeParamType(this, data); } @Override @@ -249,12 +318,25 @@ public final List<Type> interfaceBounds; } + /** + * Represents a wildcard type argument. A type argument that is not a + * wildcard type argument will be represented by a ClassType, ArrayType, etc. + * + * See: + * JVMS 4.3.4 + * TypeArgument: + * WildcardIndicator_opt FieldTypeSignature + * {@code *} + * WildcardIndicator: + * {@code +} + * {@code -} + */ public static class WildcardType extends Type { + public enum Kind { UNBOUNDED, EXTENDS, SUPER }; public WildcardType() { - this(null, null); + this(Kind.UNBOUNDED, null); } - - public WildcardType(String kind, Type boundType) { + public WildcardType(Kind kind, Type boundType) { this.kind = kind; this.boundType = boundType; } @@ -265,13 +347,19 @@ @Override public String toString() { - if (kind == null) - return "?"; - else - return "? " + kind + " " + boundType; + switch (kind) { + case UNBOUNDED: + return "?"; + case EXTENDS: + return "? extends " + boundType; + case SUPER: + return "? super " + boundType; + default: + throw new AssertionError(); + } } - public final String kind; + public final Kind kind; public final Type boundType; } }
--- a/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java Sun Nov 01 15:21:14 2009 +0000 @@ -120,6 +120,14 @@ } + // force subtypes to define equals + @Override + public abstract boolean equals(Object other); + + // force subtypes to define hashCode + @Override + public abstract int hashCode(); + /** The file manager that created this JavaFileObject. */ protected final JavacFileManager fileManager; }
--- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Sun Nov 01 15:21:14 2009 +0000 @@ -968,7 +968,7 @@ } else { File siblingDir = null; if (sibling != null && sibling instanceof RegularFileObject) { - siblingDir = ((RegularFileObject)sibling).f.getParentFile(); + siblingDir = ((RegularFileObject)sibling).file.getParentFile(); } return new RegularFileObject(this, new File(siblingDir, fileName.basename())); }
--- a/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Sun Nov 01 15:21:14 2009 +0000 @@ -33,6 +33,8 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; import java.net.URI; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -53,7 +55,8 @@ */ private boolean hasParents = false; private String name; - final File f; + final File file; + private Reference<File> absFileRef; public RegularFileObject(JavacFileManager fileManager, File f) { this(fileManager, f.getName(), f); @@ -65,17 +68,17 @@ throw new IllegalArgumentException("directories not supported"); } this.name = name; - this.f = f; + this.file = f; } @Override public URI toUri() { - return f.toURI().normalize(); + return file.toURI().normalize(); } @Override public String getName() { - return f.getPath(); + return file.getPath(); } @Override @@ -90,20 +93,20 @@ @Override public InputStream openInputStream() throws IOException { - return new FileInputStream(f); + return new FileInputStream(file); } @Override public OutputStream openOutputStream() throws IOException { ensureParentDirectoriesExist(); - return new FileOutputStream(f); + return new FileOutputStream(file); } @Override public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { CharBuffer cb = fileManager.getCachedContent(this); if (cb == null) { - InputStream in = new FileInputStream(f); + InputStream in = new FileInputStream(file); try { ByteBuffer bb = fileManager.makeByteBuffer(in); JavaFileObject prev = fileManager.log.useSource(this); @@ -126,17 +129,17 @@ @Override public Writer openWriter() throws IOException { ensureParentDirectoriesExist(); - return new OutputStreamWriter(new FileOutputStream(f), fileManager.getEncodingName()); + return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName()); } @Override public long getLastModified() { - return f.lastModified(); + return file.lastModified(); } @Override public boolean delete() { - return f.delete(); + return file.delete(); } @Override @@ -146,7 +149,7 @@ @Override protected String inferBinaryName(Iterable<? extends File> path) { - String fPath = f.getPath(); + String fPath = file.getPath(); //System.err.println("RegularFileObject " + file + " " +r.getPath()); for (File dir: path) { //System.err.println("dir: " + dir); @@ -178,7 +181,7 @@ if (name.equalsIgnoreCase(n)) { try { // allow for Windows - return f.getCanonicalFile().getName().equals(n); + return file.getCanonicalFile().getName().equals(n); } catch (IOException e) { } } @@ -187,7 +190,7 @@ private void ensureParentDirectoriesExist() throws IOException { if (!hasParents) { - File parent = f.getParentFile(); + File parent = file.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) { if (!parent.exists() || !parent.isDirectory()) { @@ -199,21 +202,34 @@ } } + /** + * Check if two file objects are equal. + * Two RegularFileObjects are equal if the absolute paths of the underlying + * files are equal. + */ @Override public boolean equals(Object other) { - if (!(other instanceof RegularFileObject)) { + if (this == other) + return true; + + if (!(other instanceof RegularFileObject)) return false; - } + RegularFileObject o = (RegularFileObject) other; - try { - return f.equals(o.f) || f.getCanonicalFile().equals(o.f.getCanonicalFile()); - } catch (IOException e) { - return false; - } + return getAbsoluteFile().equals(o.getAbsoluteFile()); } @Override public int hashCode() { - return f.hashCode(); + return getAbsoluteFile().hashCode(); + } + + private File getAbsoluteFile() { + File absFile = (absFileRef == null ? null : absFileRef.get()); + if (absFile == null) { + absFile = file.getAbsoluteFile(); + absFileRef = new SoftReference<File>(absFile); + } + return absFile; } }
--- a/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/SymbolArchive.java Sun Nov 01 15:21:14 2009 +0000 @@ -76,13 +76,13 @@ @Override public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { RelativeDirectory prefix_subdir = new RelativeDirectory(prefix, subdirectory.path); - ZipEntry ze = new RelativeFile(prefix_subdir, file).getZipEntry(zdir); + ZipEntry ze = new RelativeFile(prefix_subdir, file).getZipEntry(zfile); return new SymbolFileObject(this, file, ze); } @Override public String toString() { - return "SymbolArchive[" + zdir.getName() + "]"; + return "SymbolArchive[" + zfile.getName() + "]"; } /**
--- a/src/share/classes/com/sun/tools/javac/file/ZipArchive.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/ZipArchive.java Sun Nov 01 15:21:14 2009 +0000 @@ -47,6 +47,8 @@ import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.util.List; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; /** * <p><b>This is NOT part of any API supported by Sun Microsystems. @@ -56,20 +58,20 @@ */ public class ZipArchive implements Archive { - public ZipArchive(JavacFileManager fm, ZipFile zdir) throws IOException { - this(fm, zdir, true); + public ZipArchive(JavacFileManager fm, ZipFile zfile) throws IOException { + this(fm, zfile, true); } - protected ZipArchive(JavacFileManager fm, ZipFile zdir, boolean initMap) throws IOException { + protected ZipArchive(JavacFileManager fm, ZipFile zfile, boolean initMap) throws IOException { this.fileManager = fm; - this.zdir = zdir; + this.zfile = zfile; this.map = new HashMap<RelativeDirectory,List<String>>(); if (initMap) initMap(); } protected void initMap() throws IOException { - for (Enumeration<? extends ZipEntry> e = zdir.entries(); e.hasMoreElements(); ) { + for (Enumeration<? extends ZipEntry> e = zfile.entries(); e.hasMoreElements(); ) { ZipEntry entry; try { entry = e.nextElement(); @@ -110,7 +112,7 @@ } public JavaFileObject getFileObject(RelativeDirectory subdirectory, String file) { - ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zdir); + ZipEntry ze = new RelativeFile(subdirectory, file).getZipEntry(zfile); return new ZipFileObject(this, file, ze); } @@ -119,17 +121,39 @@ } public void close() throws IOException { - zdir.close(); + zfile.close(); } @Override public String toString() { - return "ZipArchive[" + zdir.getName() + "]"; + return "ZipArchive[" + zfile.getName() + "]"; + } + + private File getAbsoluteFile() { + File absFile = (absFileRef == null ? null : absFileRef.get()); + if (absFile == null) { + absFile = new File(zfile.getName()).getAbsoluteFile(); + absFileRef = new SoftReference<File>(absFile); + } + return absFile; } + /** + * The file manager that created this archive. + */ protected JavacFileManager fileManager; + /** + * The index for the contents of this archive. + */ protected final Map<RelativeDirectory,List<String>> map; - protected final ZipFile zdir; + /** + * The zip file for the archive. + */ + protected final ZipFile zfile; + /** + * A reference to the absolute filename for the zip file for the archive. + */ + protected Reference<File> absFileRef; /** * A subclass of JavaFileObject representing zip entries. @@ -148,18 +172,18 @@ } public URI toUri() { - File zipFile = new File(zarch.zdir.getName()); + File zipFile = new File(zarch.zfile.getName()); return createJarUri(zipFile, entry.getName()); } @Override public String getName() { - return zarch.zdir.getName() + "(" + entry.getName() + ")"; + return zarch.zfile.getName() + "(" + entry.getName() + ")"; } @Override public String getShortName() { - return new File(zarch.zdir.getName()).getName() + "(" + entry + ")"; + return new File(zarch.zfile.getName()).getName() + "(" + entry + ")"; } @Override @@ -169,7 +193,7 @@ @Override public InputStream openInputStream() throws IOException { - return zarch.zdir.getInputStream(entry); + return zarch.zfile.getInputStream(entry); } @Override @@ -181,7 +205,7 @@ public CharBuffer getCharContent(boolean ignoreEncodingErrors) throws IOException { CharBuffer cb = fileManager.getCachedContent(this); if (cb == null) { - InputStream in = zarch.zdir.getInputStream(entry); + InputStream in = zarch.zfile.getInputStream(entry); try { ByteBuffer bb = fileManager.makeByteBuffer(in); JavaFileObject prev = fileManager.log.useSource(this); @@ -237,18 +261,27 @@ return name.equals(cn + k.extension); } + /** + * Check if two file objects are equal. + * Two ZipFileObjects are equal if the absolute paths of the underlying + * zip files are equal and if the paths within those zip files are equal. + */ @Override public boolean equals(Object other) { - if (!(other instanceof ZipFileObject)) { + if (this == other) + return true; + + if (!(other instanceof ZipFileObject)) return false; - } + ZipFileObject o = (ZipFileObject) other; - return zarch.zdir.equals(o.zarch.zdir) || name.equals(o.name); + return zarch.getAbsoluteFile().equals(o.zarch.getAbsoluteFile()) + && name.equals(o.name); } @Override public int hashCode() { - return zarch.zdir.hashCode() + name.hashCode(); + return zarch.getAbsoluteFile().hashCode() + name.hashCode(); } }
--- a/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java Sun Nov 01 15:21:14 2009 +0000 @@ -30,6 +30,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Arrays; @@ -89,6 +90,7 @@ // ZipFileIndex data entries private File zipFile; + private Reference<File> absFileRef; private long zipFileLastModified = NOT_MODIFIED; private RandomAccessFile zipRandomFile; private Entry[] entries; @@ -1215,6 +1217,15 @@ return zipFile; } + File getAbsoluteFile() { + File absFile = (absFileRef == null ? null : absFileRef.get()); + if (absFile == null) { + absFile = zipFile.getAbsoluteFile(); + absFileRef = new SoftReference<File>(absFile); + } + return absFile; + } + private RelativeDirectory getRelativeDirectory(String path) { RelativeDirectory rd; SoftReference<RelativeDirectory> ref = relativeDirectoryCache.get(path);
--- a/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Sun Nov 01 15:21:14 2009 +0000 @@ -219,17 +219,27 @@ return name.equals(cn + k.extension); } + /** + * Check if two file objects are equal. + * Two ZipFileIndexFileObjects are equal if the absolute paths of the underlying + * zip files are equal and if the paths within those zip files are equal. + */ @Override public boolean equals(Object other) { + if (this == other) + return true; + if (!(other instanceof ZipFileIndexFileObject)) return false; + ZipFileIndexFileObject o = (ZipFileIndexFileObject) other; - return entry.equals(o.entry); + return zfIndex.getAbsoluteFile().equals(o.zfIndex.getAbsoluteFile()) + && name.equals(o.name); } @Override public int hashCode() { - return zipName.hashCode() + (name.hashCode() << 10); + return zfIndex.getAbsoluteFile().hashCode() + name.hashCode(); } private String getPrefixedEntryName() {
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Sun Nov 01 15:21:14 2009 +0000 @@ -2727,10 +2727,20 @@ return true; // fail-safe mode } + /** + * Check if two file objects are equal. + * SourceFileObjects are just placeholder objects for the value of a + * SourceFile attribute, and do not directly represent specific files. + * Two SourceFileObjects are equal if their names are equal. + */ @Override public boolean equals(Object other) { + if (this == other) + return true; + if (!(other instanceof SourceFileObject)) return false; + SourceFileObject o = (SourceFileObject) other; return name.equals(o.name); }
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Sun Nov 01 15:21:14 2009 +0000 @@ -876,7 +876,11 @@ } scanChar(); skipIllegalUnderscores(); - scanNumber(2); + if (digit(2) < 0) { + lexError("invalid.binary.number"); + } else { + scanNumber(2); + } } else { putChar('0'); if (ch == '_') {
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Sun Nov 01 15:21:14 2009 +0000 @@ -252,6 +252,8 @@ interface methods cannot have body compiler.err.invalid.annotation.member.type=\ invalid type for annotation member +compiler.err.invalid.binary.number=\ + binary numbers must contain at least one binary digit compiler.err.invalid.hex.number=\ hexadecimal numbers must contain at least one hexadecimal digit compiler.err.invalid.meth.decl.ret.type.req=\
--- a/src/share/classes/com/sun/tools/javap/ClassWriter.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javap/ClassWriter.java Sun Nov 01 15:21:14 2009 +0000 @@ -179,10 +179,10 @@ // The signature parser cannot disambiguate between a // FieldType and a ClassSignatureType that only contains a superclass type. if (t instanceof Type.ClassSigType) - print(t); + print(getJavaName(t.toString())); else { print(" extends "); - print(t); + print(getJavaName(t.toString())); } } catch (ConstantPoolException e) { print(report(e)); @@ -310,7 +310,7 @@ writeModifiers(flags.getMethodModifiers()); if (methodType != null) { - writeListIfNotEmpty("<", methodType.typeArgTypes, "> "); + writeListIfNotEmpty("<", methodType.typeParamTypes, "> "); } if (getName(m).equals("<init>")) { print(getJavaName(classFile));
--- a/src/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/com/sun/tools/javap/LocalVariableTypeTableWriter.java Sun Nov 01 15:21:14 2009 +0000 @@ -125,7 +125,7 @@ print(" // "); Descriptor d = new Signature(entry.signature_index); try { - print(d.getFieldType(constant_pool)); + print(d.getFieldType(constant_pool).toString().replace("/", ".")); } catch (InvalidDescriptor e) { print(report(e)); } catch (ConstantPoolException e) {
--- a/src/share/classes/javax/lang/model/util/Elements.java Mon Oct 19 13:38:09 2009 -0700 +++ b/src/share/classes/javax/lang/model/util/Elements.java Sun Nov 01 15:21:14 2009 +0000 @@ -77,9 +77,25 @@ * Returns the text of the documentation ("Javadoc") * comment of an element. * + * <p> A documentation comment of an element is a comment that + * begins with "{@code /**}" , ends with a separate + * "<code>*/</code>", and immediately precedes the element, + * ignoring white space. Therefore, a documentation comment + * contains at least three"{@code *}" characters. The text + * returned for the documentation comment is a processed form of + * the comment as it appears in source code. The leading "{@code + * /**}" and trailing "<code>*/</code>" are removed. For lines + * of the comment starting after the initial "{@code /**}", + * leading white space characters are discarded as are any + * consecutive "{@code *}" characters appearing after the white + * space or starting the line. The processed lines are then + * concatenated together (including line terminators) and + * returned. + * * @param e the element being examined * @return the documentation comment of the element, or {@code null} * if there is none + * @jls3 3.6 White Space */ String getDocComment(Element e);
--- a/test/tools/javac/api/6440528/T6440528.java Mon Oct 19 13:38:09 2009 -0700 +++ b/test/tools/javac/api/6440528/T6440528.java Sun Nov 01 15:21:14 2009 +0000 @@ -59,9 +59,9 @@ } private File getUnderlyingFile(Object o) throws Exception { - Field f = o.getClass().getDeclaredField("f"); - f.setAccessible(true); - return (File)f.get(o); + Field file = o.getClass().getDeclaredField("file"); + file.setAccessible(true); + return (File)file.get(o); } public static void main(String... args) throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/T6838467.java Sun Nov 01 15:21:14 2009 +0000 @@ -0,0 +1,249 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6838467 + * @summary JSR199 FileObjects don't obey general contract of equals. + */ + +import java.io.*; +import java.util.*; +import java.util.zip.*; +import javax.tools.*; +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.util.Context; + +public class T6838467 { + boolean fileSystemIsCaseSignificant = !new File("a").equals(new File("A")); + + enum FileKind { + DIR("dir"), + ZIP("zip"), + ZIPFILEINDEX("zip"); + FileKind(String path) { + file = new File(path); + } + final File file; + }; + + enum CompareKind { + SAME { + File other(File f) { return f; } + }, + ABSOLUTE { + File other(File f) { return f.getAbsoluteFile(); } + }, + DIFFERENT { + File other(File f) { return new File("not_" + f.getPath()); } + }, + CASEEQUIV { + File other(File f) { return new File(f.getPath().toUpperCase()); } + }; + abstract File other(File f); + }; + + String[] paths = { "p/A.java", "p/B.java", "p/C.java" }; + + public static void main(String... args) throws Exception { + new T6838467().run(); + } + + void run() throws Exception { + // on Windows, verify file system is not case significant + if (System.getProperty("os.name").toLowerCase().startsWith("windows") + && fileSystemIsCaseSignificant) { + error("fileSystemIsCaseSignificant is set on Windows."); + } + + // create a set of directories and zip files to compare + createTestDir(new File("dir"), paths); + createTestDir(new File("not_dir"), paths); + createTestZip(new File("zip"), paths); + createTestZip(new File("not_zip"), paths); + if (fileSystemIsCaseSignificant) { + createTestDir(new File("DIR"), paths); + createTestZip(new File("ZIP"), paths); + } + + // test the various sorts of file objects that can be obtained from + // the file manager, and for various values that may or may not match. + for (FileKind fk: FileKind.values()) { + for (CompareKind ck: CompareKind.values()) { + test(fk, ck); + } + } + + // verify that the various different types of file object were all + // tested + Set<String> expectClasses = new HashSet<String>(Arrays.asList( + "RegularFileObject", "ZipFileObject", "ZipFileIndexFileObject" )); + if (!foundClasses.equals(expectClasses)) { + error("expected fileobject classes not found\n" + + "expected: " + expectClasses + "\n" + + "found: " + foundClasses); + } + + if (errors > 0) + throw new Exception(errors + " errors"); + } + + void test(FileKind fk, CompareKind ck) throws IOException { + File f1 = fk.file; + JavaFileManager fm1 = createFileManager(fk, f1); + + File f2 = ck.other(fk.file); + JavaFileManager fm2 = createFileManager(fk, f2); + + try { + // If the directories or zip files match, we expect "n" matches in + // the "n-squared" comparisons to come, where "n" is the number of + // entries in the the directories or zip files. + // If the directories or zip files don't themselves match, + // we obviously don't expect any of their contents to match either. + int expect = (f1.getAbsoluteFile().equals(f2.getAbsoluteFile()) ? paths.length : 0); + + System.err.println("test " + (++count) + " " + fk + " " + ck + " " + f1 + " " + f2); + test(fm1, fm2, expect); + + } finally { + fm1.close(); + fm2.close(); + } + } + + // For a pair of file managers that may or may not have similar entries + // on the classpath, compare all files returned from one against all files + // returned from the other. For each pair of files, verify that if they + // are equal, the hashcode is equal as well, and finally verify that the + // expected number of matches was found. + void test(JavaFileManager fm1, JavaFileManager fm2, int expectEqualCount) throws IOException { + boolean foundFiles1 = false; + boolean foundFiles2 = false; + int foundEqualCount = 0; + Set<JavaFileObject.Kind> kinds = EnumSet.allOf(JavaFileObject.Kind.class); + for (FileObject fo1: fm1.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { + foundFiles1 = true; + foundClasses.add(fo1.getClass().getSimpleName()); + for (FileObject fo2: fm2.list(StandardLocation.CLASS_PATH, "p", kinds, false)) { + foundFiles2 = true; + foundClasses.add(fo1.getClass().getSimpleName()); + System.err.println("compare " + fo1 + " " + fo2); + if (fo1.equals(fo2)) { + foundEqualCount++; + int hash1 = fo1.hashCode(); + int hash2 = fo2.hashCode(); + if (hash1 != hash2) + error("hashCode error: " + fo1 + " [" + hash1 + "] " + + fo2 + " [" + hash2 + "]"); + } + } + } + if (!foundFiles1) + error("no files found for file manager 1"); + if (!foundFiles2) + error("no files found for file manager 2"); + // verify the expected number of matches were found + if (foundEqualCount != expectEqualCount) + error("expected matches not found: expected " + expectEqualCount + ", found " + foundEqualCount); + } + + // create a file manager to test a FileKind, with a given directory + // or zip file placed on the classpath + JavaFileManager createFileManager(FileKind fk, File classpath) throws IOException { + StandardJavaFileManager fm = createFileManager(fk == FileKind.ZIP); + fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(classpath)); + return fm; + } + + JavacFileManager createFileManager(boolean useJavaUtilZip) { + // javac should really not be using system properties like this + // -- it should really be using (hidden) options -- but until then + // take care to leave system properties as we find them, so as not + // to adversely affect other tests that might follow. + String prev = System.getProperty("useJavaUtilZip"); + boolean resetProperties = false; + try { + if (useJavaUtilZip) { + System.setProperty("useJavaUtilZip", "true"); + resetProperties = true; + } else if (System.getProperty("useJavaUtilZip") != null) { + System.getProperties().remove("useJavaUtilZip"); + resetProperties = true; + } + + Context c = new Context(); + return new JavacFileManager(c, false, null); + } finally { + if (resetProperties) { + if (prev == null) { + System.getProperties().remove("useJavaUtilZip"); + } else { + System.setProperty("useJavaUtilZip", prev); + } + } + } + } + + // create a directory containing a given set of paths + void createTestDir(File dir, String[] paths) throws IOException { + for (String p: paths) { + File file = new File(dir, p); + file.getParentFile().mkdirs(); + FileWriter out = new FileWriter(file); + try { + out.write(p); + } finally { + out.close(); + } + } + } + + // create a sip file containing a given set of entries + void createTestZip(File zip, String[] paths) throws IOException { + if (zip.getParentFile() != null) + zip.getParentFile().mkdirs(); + ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip)); + try { + for (String p: paths) { + ZipEntry ze = new ZipEntry(p); + zos.putNextEntry(ze); + byte[] bytes = p.getBytes(); + zos.write(bytes, 0, bytes.length); + zos.closeEntry(); + } + } finally { + zos.close(); + } + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int count; + int errors; + Set<String> foundClasses = new HashSet<String>(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/literals/T6891079.java Sun Nov 01 15:21:14 2009 +0000 @@ -0,0 +1,12 @@ +/* @test /nodynamiccopyright/ + * @bug 6891079 + * @summary Compiler allows invalid binary literals 0b and oBL + * @compile/fail/ref=T6891079.out -XDrawDiagnostics T6891079.java + */ + +class Test { + int bi = 0B; + long bl = 0BL; + int xi = 0X; + long xl = 0XL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/literals/T6891079.out Sun Nov 01 15:21:14 2009 +0000 @@ -0,0 +1,7 @@ +T6891079.java:8:14: compiler.err.invalid.binary.number +T6891079.java:9:15: compiler.err.invalid.binary.number +T6891079.java:9:18: compiler.err.expected: token.identifier +T6891079.java:10:14: compiler.err.invalid.hex.number +T6891079.java:11:15: compiler.err.invalid.hex.number +T6891079.java:11:18: compiler.err.expected: token.identifier +6 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/classfile/6888367/T6888367.java Sun Nov 01 15:21:14 2009 +0000 @@ -0,0 +1,511 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.Type.ArrayType; +import com.sun.tools.classfile.Type.ClassSigType; +import com.sun.tools.classfile.Type.ClassType; +import com.sun.tools.classfile.Type.MethodType; +import com.sun.tools.classfile.Type.SimpleType; +import com.sun.tools.classfile.Type.TypeParamType; +import com.sun.tools.classfile.Type.WildcardType; + +/* + * @test + * @bug 6888367 + * @summary classfile library parses signature attributes incorrectly + */ + +/* + * This test is a pretty detailed test both of javac signature generation and classfile + * signature parsing. The first part of the test tests all the examples given in the + * second part of the test. Each example comes with one or two annotations, @Desc, @Sig, + * for the descriptor and signature of the annotated declaration. Annotations are + * provided whenever the annotated item is expected to have a corresponding value. + * Each annotation has two argument values. The first arg is the expected value of the + * descriptor/signature as found in the class file. This value is mostly for documentation + * purposes in reading the test. The second value is the rendering of the descriptor or + * signature using a custom Type visitor that explicitly includes an indication of the + * Type classes being used to represent the descriptor/signature. Thus we test + * that the descriptor/signature is being parsed into the expected type tree structure. + */ +public class T6888367 { + + public static void main(String... args) throws Exception { + new T6888367().run(); + } + + public void run() throws Exception { + ClassFile cf = getClassFile("Test"); + + testFields(cf); + testMethods(cf); + testInnerClasses(cf); // recursive + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void testFields(ClassFile cf) throws Exception { + String cn = cf.getName(); + ConstantPool cp = cf.constant_pool; + for (Field f: cf.fields) { + test("field " + cn + "." + f.getName(cp), f.descriptor, f.attributes, cp); + } + } + + void testMethods(ClassFile cf) throws Exception { + String cn = cf.getName(); + ConstantPool cp = cf.constant_pool; + for (Method m: cf.methods) { + test("method " + cn + "." + m.getName(cp), m.descriptor, m.attributes, cp); + } + } + + void testInnerClasses(ClassFile cf) throws Exception { + ConstantPool cp = cf.constant_pool; + InnerClasses_attribute ic = + (InnerClasses_attribute) cf.attributes.get(Attribute.InnerClasses); + for (InnerClasses_attribute.Info info: ic.classes) { + String outerClassName = cp.getClassInfo(info.outer_class_info_index).getName(); + if (!outerClassName.equals(cf.getName())) { + continue; + } + String innerClassName = cp.getClassInfo(info.inner_class_info_index).getName(); + ClassFile icf = getClassFile(innerClassName); + test("class " + innerClassName, null, icf.attributes, icf.constant_pool); + testInnerClasses(icf); + } + } + + void test(String name, Descriptor desc, Attributes attrs, ConstantPool cp) + throws Exception { + AnnotValues d = getDescValue(attrs, cp); + AnnotValues s = getSigValue(attrs, cp); + if (d == null && s == null) // not a test field or method if no @Desc or @Sig given + return; + + System.err.println(name); + + if (desc != null) { + System.err.println(" descriptor: " + desc.getValue(cp)); + checkEqual(d.raw, desc.getValue(cp)); + Type dt = new Signature(desc.index).getType(cp); + checkEqual(d.type, tp.print(dt)); + } + + Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature); + if (sa != null) + System.err.println(" signature: " + sa.getSignature(cp)); + + if (s != null || sa != null) { + if (s != null && sa != null) { + checkEqual(s.raw, sa.getSignature(cp)); + Type st = new Signature(sa.signature_index).getType(cp); + checkEqual(s.type, tp.print(st)); + } else if (s != null) + error("@Sig annotation found but not Signature attribute"); + else + error("Signature attribute found but no @Sig annotation"); + } + + System.err.println(); + } + + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name + ".class"); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + AnnotValues getDescValue(Attributes attrs, ConstantPool cp) throws Exception { + return getAnnotValues(Desc.class.getName(), attrs, cp); + } + + AnnotValues getSigValue(Attributes attrs, ConstantPool cp) throws Exception { + return getAnnotValues(Sig.class.getName(), attrs, cp); + } + + static class AnnotValues { + AnnotValues(String raw, String type) { + this.raw = raw; + this.type = type; + } + final String raw; + final String type; + } + + AnnotValues getAnnotValues(String annotName, Attributes attrs, ConstantPool cp) + throws Exception { + RuntimeInvisibleAnnotations_attribute annots = + (RuntimeInvisibleAnnotations_attribute)attrs.get(Attribute.RuntimeInvisibleAnnotations); + if (annots != null) { + for (Annotation a: annots.annotations) { + if (cp.getUTF8Value(a.type_index).equals("L" + annotName + ";")) { + Annotation.Primitive_element_value pv0 = + (Annotation.Primitive_element_value) a.element_value_pairs[0].value; + Annotation.Primitive_element_value pv1 = + (Annotation.Primitive_element_value) a.element_value_pairs[1].value; + return new AnnotValues( + cp.getUTF8Value(pv0.const_value_index), + cp.getUTF8Value(pv1.const_value_index)); + } + } + } + return null; + + } + + void checkEqual(String expect, String found) { + if (!(expect == null ? found == null : expect.equals(found))) { + System.err.println("expected: " + expect); + System.err.println(" found: " + found); + error("unexpected values found"); + } + } + + void error(String msg) { + System.err.println("error: " + msg); + errors++; + } + + int errors; + + TypePrinter tp = new TypePrinter(); + + class TypePrinter implements Type.Visitor<String,Void> { + String print(Type t) { + return t == null ? null : t.accept(this, null); + } + String print(String pre, List<? extends Type> ts, String post) { + if (ts == null) + return null; + StringBuilder sb = new StringBuilder(); + sb.append(pre); + String sep = ""; + for (Type t: ts) { + sb.append(sep); + sb.append(print(t)); + sep = ","; + } + sb.append(post); + return sb.toString(); + } + + public String visitSimpleType(SimpleType type, Void p) { + return "S{" + type.name + "}"; + } + + public String visitArrayType(ArrayType type, Void p) { + return "A{" + print(type.elemType) + "}"; + } + + public String visitMethodType(MethodType type, Void p) { + StringBuilder sb = new StringBuilder(); + sb.append("M{"); + if (type.typeParamTypes != null) + sb.append(print("<", type.typeParamTypes, ">")); + sb.append(print(type.returnType)); + sb.append(print("(", type.paramTypes, ")")); + if (type.throwsTypes != null) + sb.append(print("", type.throwsTypes, "")); + sb.append("}"); + return sb.toString(); + } + + public String visitClassSigType(ClassSigType type, Void p) { + StringBuilder sb = new StringBuilder(); + sb.append("CS{"); + if (type.typeParamTypes != null) + sb.append(print("<", type.typeParamTypes, ">")); + sb.append(print(type.superclassType)); + if (type.superinterfaceTypes != null) + sb.append(print("i(", type.superinterfaceTypes, ")")); + sb.append("}"); + return sb.toString(); + } + + public String visitClassType(ClassType type, Void p) { + StringBuilder sb = new StringBuilder(); + sb.append("C{"); + if (type.outerType != null) { + sb.append(print(type.outerType)); + sb.append("."); + } + sb.append(type.name); + if (type.typeArgs != null) + sb.append(print("<", type.typeArgs, ">")); + sb.append("}"); + return sb.toString(); + } + + public String visitTypeParamType(TypeParamType type, Void p) { + StringBuilder sb = new StringBuilder(); + sb.append("TA{"); + sb.append(type.name); + if (type.classBound != null) { + sb.append(":c"); + sb.append(print(type.classBound)); + } + if (type.interfaceBounds != null) + sb.append(print(":i", type.interfaceBounds, "")); + sb.append("}"); + return sb.toString(); + } + + public String visitWildcardType(WildcardType type, Void p) { + switch (type.kind) { + case UNBOUNDED: + return "W{?}"; + case EXTENDS: + return "W{e," + print(type.boundType) + "}"; + case SUPER: + return "W{s," + print(type.boundType) + "}"; + default: + throw new AssertionError(); + } + } + + }; +} + + +@interface Desc { + String d(); + String t(); +} + +@interface Sig { + String s(); + String t(); +} + +class Clss { } +interface Intf { } +class GenClss<T> { } + +class Test { + // fields + + @Desc(d="Z", t="S{boolean}") + boolean z; + + @Desc(d="B", t="S{byte}") + byte b; + + @Desc(d="C", t="S{char}") + char c; + + @Desc(d="D", t="S{double}") + double d; + + @Desc(d="F", t="S{float}") + float f; + + @Desc(d="I", t="S{int}") + int i; + + @Desc(d="J", t="S{long}") + long l; + + @Desc(d="S", t="S{short}") + short s; + + @Desc(d="LClss;", t="C{Clss}") + Clss clss; + + @Desc(d="LIntf;", t="C{Intf}") + Intf intf; + + @Desc(d="[I", t="A{S{int}}") + int[] ai; + + @Desc(d="[LClss;", t="A{C{Clss}}") + Clss[] aClss; + + @Desc(d="LGenClss;", t="C{GenClss}") + @Sig(s="LGenClss<LClss;>;", t="C{GenClss<C{Clss}>}") + GenClss<Clss> genClass; + + // methods, return types + + @Desc(d="()V", t="M{S{void}()}") + void mv0() { } + + @Desc(d="()I", t="M{S{int}()}") + int mi0() { return 0; } + + @Desc(d="()LClss;", t="M{C{Clss}()}") + Clss mclss0() { return null; } + + @Desc(d="()[I", t="M{A{S{int}}()}") + int[] mai0() { return null; } + + @Desc(d="()[LClss;", t="M{A{C{Clss}}()}") + Clss[] maClss0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="()LGenClss<LClss;>;", t="M{C{GenClss<C{Clss}>}()}") + GenClss<Clss> mgenClss0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="()LGenClss<*>;", t="M{C{GenClss<W{?}>}()}") + GenClss<?> mgenClssW0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="()LGenClss<+LClss;>;", t="M{C{GenClss<W{e,C{Clss}}>}()}") + GenClss<? extends Clss> mgenClssWExtClss0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="()LGenClss<-LClss;>;", t="M{C{GenClss<W{s,C{Clss}}>}()}") + GenClss<? super Clss> mgenClssWSupClss0() { return null; } + + @Desc(d="()Ljava/lang/Object;", t="M{C{java/lang/Object}()}") + @Sig(s="<T:Ljava/lang/Object;>()TT;", t="M{<TA{T:cC{java/lang/Object}}>S{T}()}") + <T> T mt0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="<T:Ljava/lang/Object;>()LGenClss<+TT;>;", + t="M{<TA{T:cC{java/lang/Object}}>C{GenClss<W{e,S{T}}>}()}") + <T> GenClss<? extends T> mgenClssWExtT0() { return null; } + + @Desc(d="()LGenClss;", t="M{C{GenClss}()}") + @Sig(s="<T:Ljava/lang/Object;>()LGenClss<-TT;>;", t="M{<TA{T:cC{java/lang/Object}}>C{GenClss<W{s,S{T}}>}()}") + <T> GenClss<? super T> mgenClssWSupT0() { return null; } + + // methods, arg types + + @Desc(d="(I)V", t="M{S{void}(S{int})}") + void mi1(int arg) { } + + @Desc(d="(LClss;)V", t="M{S{void}(C{Clss})}") + void mclss1(Clss arg) { } + + @Desc(d="([I)V", t="M{S{void}(A{S{int}})}") + void mai1(int[] arg) { } + + @Desc(d="([LClss;)V", t="M{S{void}(A{C{Clss}})}") + void maClss1(Clss[] arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="(LGenClss<LClss;>;)V", t="M{S{void}(C{GenClss<C{Clss}>})}") + void mgenClss1(GenClss<Clss> arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="(LGenClss<*>;)V", t="M{S{void}(C{GenClss<W{?}>})}") + void mgenClssW1(GenClss<?> arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="(LGenClss<+LClss;>;)V", t="M{S{void}(C{GenClss<W{e,C{Clss}}>})}") + void mgenClssWExtClss1(GenClss<? extends Clss> arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="(LGenClss<-LClss;>;)V", t="M{S{void}(C{GenClss<W{s,C{Clss}}>})}") + void mgenClssWSupClss1(GenClss<? super Clss> arg) { } + + @Desc(d="(Ljava/lang/Object;)V", t="M{S{void}(C{java/lang/Object})}") + @Sig(s="<T:Ljava/lang/Object;>(TT;)V", + t="M{<TA{T:cC{java/lang/Object}}>S{void}(S{T})}") + <T> void mt1(T arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="<T:Ljava/lang/Object;>(LGenClss<+TT;>;)V", + t="M{<TA{T:cC{java/lang/Object}}>S{void}(C{GenClss<W{e,S{T}}>})}") + <T> void mgenClssWExtT1(GenClss<? extends T> arg) { } + + @Desc(d="(LGenClss;)V", t="M{S{void}(C{GenClss})}") + @Sig(s="<T:Ljava/lang/Object;>(LGenClss<-TT;>;)V", + t="M{<TA{T:cC{java/lang/Object}}>S{void}(C{GenClss<W{s,S{T}}>})}") + <T> void mgenClssWSupT1(GenClss<? super T> arg) { } + + // methods, throws + + @Desc(d="()V", t="M{S{void}()}") + void m_E() throws Exception { } + + @Desc(d="()V", t="M{S{void}()}") + @Sig(s="<T:Ljava/lang/Throwable;>()V^TT;", + t="M{<TA{T:cC{java/lang/Throwable}}>S{void}()S{T}}") + <T extends Throwable> void m_T() throws T { } + + // inner classes + + static class X { + // no sig + class P { } + + @Sig(s="<TQ:Ljava/lang/Object;>LTest$X$P;", + t="CS{<TA{TQ:cC{java/lang/Object}}>C{Test$X$P}}") + class Q<TQ> extends P { } + + @Sig(s="<TR:Ljava/lang/Object;>LTest$X$Q<TTR;>;", + t="CS{<TA{TR:cC{java/lang/Object}}>C{Test$X$Q<S{TR}>}}") + class R<TR> extends Q<TR> { } + } + + @Sig(s="<TY:Ljava/lang/Object;>Ljava/lang/Object;", + t="CS{<TA{TY:cC{java/lang/Object}}>C{java/lang/Object}}") + static class Y<TY> { + // no sig + class P { } + + @Sig(s="<TQ:Ljava/lang/Object;>LTest$Y<TTY;>.P;", + t="CS{<TA{TQ:cC{java/lang/Object}}>C{C{Test$Y<S{TY}>}.P}}") + class Q<TQ> extends P { } + + @Sig(s="<TR:Ljava/lang/Object;>LTest$Y<TTY;>.Q<TTR;>;", + t="CS{<TA{TR:cC{java/lang/Object}}>C{C{Test$Y<S{TY}>}.Q<S{TR}>}}") + class R<TR> extends Q<TR> { + // no sig + class R1 { } + + @Sig(s="<TR2:Ljava/lang/Object;>LTest$Y<TTY;>.R<TTR;>.R1;", + t="CS{<TA{TR2:cC{java/lang/Object}}>C{C{C{Test$Y<S{TY}>}.R<S{TR}>}.R1}}") + class R2<TR2> extends R1 { } + } + + @Sig(s="LTest$Y<TTY;>.Q<TTY;>;", t="C{C{Test$Y<S{TY}>}.Q<S{TY}>}") + class S extends Q<TY> { + // no sig + class S1 { } + + @Sig(s="<TS2:Ljava/lang/Object;>LTest$Y<TTY;>.S.S1;", + t="CS{<TA{TS2:cC{java/lang/Object}}>C{C{C{Test$Y<S{TY}>}.S}.S1}}") + class S2<TS2> extends S1 { } + + @Sig(s="LTest$Y<TTY;>.S.S2<TTY;>;", + t="C{C{C{Test$Y<S{TY}>}.S}.S2<S{TY}>}") + class S3 extends S2<TY> { } + } + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/classfile/T6887895.java Sun Nov 01 15:21:14 2009 +0000 @@ -0,0 +1,121 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6887895 + * @summary CONSTANT_Class_info getBaseName does not handle arrays of primitives correctly + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +public class T6887895 { + public static void main(String[] args) throws Exception { + new T6887895().run(); + } + + void run() throws Exception { + Set<String> found = new TreeSet<String>(); + + ClassFile cf = getClassFile("T6887895$Test.class"); + for (CPInfo cpInfo: cf.constant_pool.entries()) { + if (cpInfo instanceof CONSTANT_Class_info) { + CONSTANT_Class_info info = (CONSTANT_Class_info) cpInfo; + String name = info.getName(); + String baseName = info.getBaseName(); + System.out.println("found: " + name + " " + baseName); + if (baseName != null) + found.add(baseName); + } + } + + String[] expectNames = { + "java/lang/Object", + "java/lang/String", + "T6887895", + "T6887895$Test" + }; + + Set<String> expect = new TreeSet<String>(Arrays.asList(expectNames)); + if (!found.equals(expect)) { + System.err.println("found: " + found); + System.err.println("expect: " + expect); + throw new Exception("unexpected values found"); + } + } + + ClassFile getClassFile(String name) throws IOException, ConstantPoolException { + URL url = getClass().getResource(name); + InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + class Test { + void m() { + boolean[] az = new boolean[0]; + boolean[][] aaz = new boolean[0][]; + boolean[][][] aaaz = new boolean[0][][]; + + byte[] ab = new byte[0]; + byte[][] aab = new byte[0][]; + byte[][][] aaab = new byte[0][][]; + + char[] ac = new char[0]; + char[][] aac = new char[0][]; + char[][][] aaac = new char[0][][]; + + double[] ad = new double[0]; + double[][] aad = new double[0][]; + double[][][] aaad = new double[0][][]; + + float[] af = new float[0]; + float[][] aaf = new float[0][]; + float[][][] aaaf = new float[0][][]; + + int[] ai = new int[0]; + int[][] aai = new int[0][]; + int[][][] aaai = new int[0][][]; + + long[] al = new long[0]; + long[][] aal = new long[0][]; + long[][][] aaal = new long[0][][]; + + short[] as = new short[0]; + short[][] aas = new short[0][]; + short[][][] aaas = new short[0][][]; + + String[] aS = new String[0]; + String[][] aaS = new String[0][]; + String[][][] aaaS = new String[0][][]; + } + } +} +