diff options
author | jfrijters <jfrijters> | 2013-02-21 20:56:08 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2013-02-21 20:56:08 +0400 |
commit | 4bf1c0dca4e97a229381fd59592a1ce3224ea87a (patch) | |
tree | 63be3189e562949ee7d39e2f35f8f1c7caa3ae89 | |
parent | a1ba4a280cb24b022833d7cf301c96ce11a8cd89 (diff) |
Removed the old Java stub class generator and replaced it with the ikvmstub core.
-rw-r--r-- | classpath/gnu/java/net/protocol/ikvmres/Handler.java | 5 | ||||
-rw-r--r-- | classpath/ikvm/internal/stubgen/StubGenerator.java | 1603 | ||||
-rw-r--r-- | ikvmstub/ikvmstub.8.csproj | 5 | ||||
-rw-r--r-- | ikvmstub/ikvmstub.build | 5 | ||||
-rw-r--r-- | ikvmstub/ikvmstub.cs | 460 | ||||
-rw-r--r-- | openjdk/allsources.lst | 1 | ||||
-rw-r--r-- | openjdk/response.txt | 41 | ||||
-rw-r--r-- | runtime/IKVM.Runtime.8.csproj | 3 | ||||
-rw-r--r-- | runtime/common.cs | 10 | ||||
-rw-r--r-- | runtime/openjdk.cs | 1 | ||||
-rw-r--r-- | runtime/runtime.build | 3 | ||||
-rw-r--r-- | runtime/stubgen/ClassFileWriter.cs (renamed from ikvmstub/ClassFileWriter.cs) | 0 | ||||
-rw-r--r-- | runtime/stubgen/SerialVersionUID.cs (renamed from ikvmstub/SerialVersionUID.cs) | 2 | ||||
-rw-r--r-- | runtime/stubgen/StubGenerator.cs | 525 | ||||
-rw-r--r-- | runtime/vfs.cs | 5 |
15 files changed, 579 insertions, 2090 deletions
diff --git a/classpath/gnu/java/net/protocol/ikvmres/Handler.java b/classpath/gnu/java/net/protocol/ikvmres/Handler.java index b8d0ae29..e122c484 100644 --- a/classpath/gnu/java/net/protocol/ikvmres/Handler.java +++ b/classpath/gnu/java/net/protocol/ikvmres/Handler.java @@ -119,7 +119,7 @@ public class Handler extends URLStreamHandler try { Class c = Class.forName(resource.substring(1, resource.length() - 6).replace('/', '.'), false, loader); - return new ByteArrayInputStream(ikvm.internal.stubgen.StubGenerator.generateStub(c)); + return new ByteArrayInputStream(GenerateStub(c)); } catch(ClassNotFoundException _) { @@ -152,7 +152,7 @@ public class Handler extends URLStreamHandler Class c = LoadClassFromAssembly(asm, resource.substring(1, resource.length() - 6).replace('/', '.')); if(c != null) { - return new ByteArrayInputStream(ikvm.internal.stubgen.StubGenerator.generateStub(c)); + return new ByteArrayInputStream(GenerateStub(c)); } } throw (FileNotFoundException)new FileNotFoundException().initCause(x); @@ -163,6 +163,7 @@ public class Handler extends URLStreamHandler } } + private static native byte[] GenerateStub(Class c); private static native cli.System.IO.Stream ReadResourceFromAssemblyImpl(Assembly asm, String resource); private static native Class LoadClassFromAssembly(Assembly asm, String className); private static native Assembly LoadAssembly(String name) diff --git a/classpath/ikvm/internal/stubgen/StubGenerator.java b/classpath/ikvm/internal/stubgen/StubGenerator.java deleted file mode 100644 index bfb1eeb5..00000000 --- a/classpath/ikvm/internal/stubgen/StubGenerator.java +++ /dev/null @@ -1,1603 +0,0 @@ -/* - Copyright (C) 2006, 2007 Jeroen Frijters - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jeroen Frijters - jeroen@frijters.net - -*/ - -package ikvm.internal.stubgen; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.ObjectStreamClass; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Hashtable; - -public final class StubGenerator implements PrivilegedAction<byte[]> -{ - private Class c; - - private StubGenerator(Class c) - { - this.c = c; - } - - @ikvm.lang.Internal - public static byte[] generateStub(Class c) - { - return AccessController.doPrivileged(new StubGenerator(c)); - } - - public byte[] run() - { - boolean includeNonPublicInterfaces = !"true".equalsIgnoreCase(System.getProperty("ikvm.stubgen.skipNonPublicInterfaces")); - Class outer = c.getDeclaringClass(); - String name = c.getName().replace('.', '/'); - String superClass = null; - if(c.getSuperclass() != null) - { - superClass = c.getSuperclass().getName().replace('.', '/'); - } - if(c.isInterface()) - { - superClass = "java/lang/Object"; - } - ClassFileWriter f = new ClassFileWriter(getRealModifiers(c), name, superClass, 0, 49); - String genericSignature = BuildGenericSignature(c); - if(genericSignature != null) - { - f.AddStringAttribute("Signature", genericSignature); - } - f.AddStringAttribute("IKVM.NET.Assembly", getAssemblyName(c)); - if(isClassDeprecated(c)) - { - f.AddAttribute(new DeprecatedAttribute(f)); - } - InnerClassesAttribute innerClassesAttribute = null; - if(outer != null) - { - innerClassesAttribute = new InnerClassesAttribute(f); - String innername = name; - // TODO instead of mangling the name, maybe we chould use the new Class APIs (e.g. getSimpleName()) - int idx = name.lastIndexOf('$'); - if(idx >= 0) - { - innername = innername.substring(idx + 1); - } - innerClassesAttribute.Add(name, outer.getName().replace('.', '/'), innername, getModifiers(c)); - } - Class[] interfaces = c.getInterfaces(); - for(int i = 0; i < interfaces.length; i++) - { - if(includeNonPublicInterfaces || Modifier.isPublic(interfaces[i].getModifiers())) - { - f.AddInterface(interfaces[i].getName().replace('.', '/')); - } - } - Class[] innerClasses = c.getDeclaredClasses(); - for(int i = 0; i < innerClasses.length; i++) - { - // TODO add private export support (for bcel) - int mods = getModifiers(innerClasses[i]); - if((mods & (Modifiers.Public | Modifiers.Protected)) != 0) - { - if(innerClassesAttribute == null) - { - innerClassesAttribute = new InnerClassesAttribute(f); - } - String namePart = innerClasses[i].getName(); - // TODO name mangling - namePart = namePart.substring(namePart.lastIndexOf('$') + 1); - innerClassesAttribute.Add(innerClasses[i].getName().replace('.', '/'), name, namePart, mods); - } - } - java.lang.reflect.Constructor[] constructors = c.getDeclaredConstructors(); - for(int i = 0; i < constructors.length; i++) - { - int mods = constructors[i].getModifiers(); - if((mods & (Modifiers.Public | Modifiers.Protected)) != 0) - { - if(constructors[i].isSynthetic()) - { - mods |= Modifiers.Synthetic; - } - if(constructors[i].isVarArgs()) - { - mods |= Modifiers.VarArgs; - } - Class[] args = constructors[i].getParameterTypes(); - FieldOrMethod m = f.AddMethod(mods, "<init>", MakeSig(args, java.lang.Void.TYPE)); - CodeAttribute code = new CodeAttribute(f); - code.SetMaxLocals(args.length * 2 + 1); - code.SetMaxStack(3); - short index1 = f.AddClass("java/lang/UnsatisfiedLinkError"); - short index2 = f.AddString("ikvmstub generated stubs can only be used on IKVM.NET"); - short index3 = f.AddMethodRef("java/lang/UnsatisfiedLinkError", "<init>", "(Ljava/lang/String;)V"); - code.SetByteCode(new byte[] - { - (byte)187, (byte)(index1 >> 8), (byte)index1, // new java/lang/UnsatisfiedLinkError - (byte)89, // dup - (byte)19, (byte)(index2 >> 8), (byte)index2, // ldc_w "..." - (byte)183, (byte)(index3 >> 8), (byte)index3, // invokespecial java/lang/UnsatisfiedLinkError/init()V - (byte)191 // athrow - }); - m.AddAttribute(code); - AddExceptions(f, m, constructors[i].getExceptionTypes()); - if(isMethodDeprecated(constructors[i])) - { - m.AddAttribute(new DeprecatedAttribute(f)); - } - String signature = BuildGenericSignature(constructors[i].getTypeParameters(), - constructors[i].getGenericParameterTypes(), Void.TYPE, constructors[i].getGenericExceptionTypes()); - if (signature != null) - { - m.AddAttribute(f.MakeStringAttribute("Signature", signature)); - } - Annotation[] annotations = constructors[i].getDeclaredAnnotations(); - if(annotations.length > 0) - { - m.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, annotations)); - } - Annotation[][] parameterAnnotations = constructors[i].getParameterAnnotations(); - if(hasParameterAnnotations(parameterAnnotations)) - { - m.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, parameterAnnotations)); - } - } - } - java.lang.reflect.Method[] methods = c.getDeclaredMethods(); - for(int i = 0; i < methods.length; i++) - { - int mods = methods[i].getModifiers(); - if((mods & (Modifiers.Public | Modifiers.Protected)) != 0) - { - if((mods & Modifiers.Abstract) == 0) - { - mods |= Modifiers.Native; - } - if(methods[i].isBridge()) - { - mods |= Modifiers.Bridge; - } - if(methods[i].isSynthetic()) - { - mods |= Modifiers.Synthetic; - } - if(methods[i].isVarArgs()) - { - mods |= Modifiers.VarArgs; - } - Class[] args = methods[i].getParameterTypes(); - Class retType = methods[i].getReturnType(); - FieldOrMethod m = f.AddMethod(mods, methods[i].getName(), MakeSig(args, retType)); - AddExceptions(f, m, methods[i].getExceptionTypes()); - if(isMethodDeprecated(methods[i])) - { - m.AddAttribute(new DeprecatedAttribute(f)); - } - String signature = BuildGenericSignature(methods[i].getTypeParameters(), - methods[i].getGenericParameterTypes(), methods[i].getGenericReturnType(), - methods[i].getGenericExceptionTypes()); - if (signature != null) - { - m.AddAttribute(f.MakeStringAttribute("Signature", signature)); - } - Object defaultValue = methods[i].getDefaultValue(); - if(defaultValue != null) - { - m.AddAttribute(new AnnotationDefaultClassFileAttribute(f, defaultValue)); - } - Annotation[] annotations = methods[i].getDeclaredAnnotations(); - if(annotations.length > 0) - { - m.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, annotations)); - } - Annotation[][] parameterAnnotations = methods[i].getParameterAnnotations(); - if(hasParameterAnnotations(parameterAnnotations)) - { - m.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, parameterAnnotations)); - } - } - } - java.lang.reflect.Field[] fields = c.getDeclaredFields(); - for(int i = 0; i < fields.length; i++) - { - int mods = fields[i].getModifiers(); - if((mods & (Modifiers.Public | Modifiers.Protected)) != 0) - { - // NOTE we can't use Field.get() because that will run the static initializer and - // also won't allow us to see the difference between constants and blank final fields, - // so we use a "native" method. - Object constantValue = getFieldConstantValue(fields[i]); - Class fieldType = fields[i].getType(); - if(fields[i].isEnumConstant()) - { - mods |= Modifiers.Enum; - } - if(fields[i].isSynthetic()) - { - mods |= Modifiers.Synthetic; - } - FieldOrMethod fld = f.AddField(mods, fields[i].getName(), ClassToSig(fieldType), constantValue); - if(isFieldDeprecated(fields[i])) - { - fld.AddAttribute(new DeprecatedAttribute(f)); - } - if(fields[i].getGenericType() != fieldType) - { - fld.AddAttribute(f.MakeStringAttribute("Signature", ToSigForm(fields[i].getGenericType()))); - } - Annotation[] annotations = fields[i].getDeclaredAnnotations(); - if(annotations.length > 0) - { - fld.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, annotations)); - } - } - } - if(innerClassesAttribute != null) - { - f.AddAttribute(innerClassesAttribute); - } - Annotation[] annotations = c.getDeclaredAnnotations(); - if(annotations.length > 0) - { - f.AddAttribute(new RuntimeVisibleAnnotationsAttribute(f, annotations)); - } - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - f.Write(baos); - return baos.toByteArray(); - } - catch (IOException x) - { - throw new Error(x); - } - } - - private static boolean hasParameterAnnotations(Annotation[][] parameterAnnotations) - { - for(int i = 0; i < parameterAnnotations.length; i++) - { - if(parameterAnnotations[i].length > 0) - { - return true; - } - } - return false; - } - - private static int getModifiers(Class c) - { - int mods = c.getModifiers(); - if(c.isAnnotation()) - { - mods |= Modifiers.Annotation; - } - if(c.isEnum()) - { - mods |= Modifiers.Enum; - } - if(c.isSynthetic()) - { - mods |= Modifiers.Synthetic; - } - return mods; - } - - private static native int getRealModifiers(Class c); - private static native String getAssemblyName(Class c); - private static native boolean isClassDeprecated(Class c); - private static native boolean isFieldDeprecated(Object field); - private static native boolean isMethodDeprecated(Object method); - private static native Object getFieldConstantValue(Object field); - - private static void AddExceptions(ClassFileWriter f, FieldOrMethod m, Class[] exceptions) - { - if (exceptions.length > 0) - { - ExceptionsAttribute attrib = new ExceptionsAttribute(f); - for (int i = 0; i < exceptions.length; i++) - { - attrib.Add(exceptions[i].getName().replace('.', '/')); - } - m.AddAttribute(attrib); - } - } - - private static String MakeSig(Class[] args, Class ret) - { - StringBuilder sb = new StringBuilder(); - sb.append('('); - for(int i = 0; i < args.length; i++) - { - sb.append(ClassToSig(args[i])); - } - sb.append(')'); - sb.append(ClassToSig(ret)); - return sb.toString(); - } - - private static String ClassToSig(Class c) - { - if(c.isPrimitive()) - { - if(c == Void.TYPE) - { - return "V"; - } - else if(c == Byte.TYPE) - { - return "B"; - } - else if(c == Boolean.TYPE) - { - return "Z"; - } - else if(c == Short.TYPE) - { - return "S"; - } - else if(c == Character.TYPE) - { - return "C"; - } - else if(c == Integer.TYPE) - { - return "I"; - } - else if(c == Long.TYPE) - { - return "J"; - } - else if(c == Float.TYPE) - { - return "F"; - } - else if(c == Double.TYPE) - { - return "D"; - } - else - { - throw new Error(); - } - } - else if(c.isArray()) - { - return "[" + ClassToSig(c.getComponentType()); - } - else - { - return "L" + c.getName().replace('.', '/') + ";"; - } - } - - private static String BuildGenericSignature(Class c) - { - boolean isgeneric = false; - StringBuilder sb = new StringBuilder(); - java.lang.reflect.TypeVariable[] vars = c.getTypeParameters(); - if(vars.length > 0) - { - isgeneric = true; - sb.append('<'); - for (int i = 0; i < vars.length; i++) - { - java.lang.reflect.TypeVariable t = vars[i]; - sb.append(t.getName()); - boolean first = true; - java.lang.reflect.Type[] bounds = t.getBounds(); - for (int j = 0; j < bounds.length; j++) - { - java.lang.reflect.Type bound = bounds[j]; - if(first) - { - first = false; - if(bound instanceof Class) - { - // HACK I don't really understand what the proper criterion is to decide this - if(((Class)bound).isInterface()) - { - sb.append(':'); - } - } - } - sb.append(':').append(ToSigForm(bound)); - } - } - sb.append('>'); - } - java.lang.reflect.Type superclass = c.getGenericSuperclass(); - if(superclass == null) - { - sb.append("Ljava/lang/Object;"); - } - else - { - isgeneric |= !(superclass instanceof Class); - sb.append(ToSigForm(superclass)); - } - java.lang.reflect.Type[] interfaces = c.getGenericInterfaces(); - for (int i = 0; i < interfaces.length; i++) - { - java.lang.reflect.Type t = interfaces[i]; - isgeneric |= !(t instanceof Class); - sb.append(ToSigForm(t)); - } - if(isgeneric) - { - return sb.toString(); - } - return null; - } - - private static String BuildGenericSignature(java.lang.reflect.TypeVariable[] typeParameters, - java.lang.reflect.Type[] parameterTypes, java.lang.reflect.Type returnType, - java.lang.reflect.Type[] exceptionTypes) - { - boolean isgeneric = false; - StringBuilder sb = new StringBuilder(); - if(typeParameters.length > 0) - { - isgeneric = true; - sb.append('<'); - for (int i = 0; i < typeParameters.length; i++) - { - java.lang.reflect.TypeVariable t = typeParameters[i]; - sb.append(t.getName()); - java.lang.reflect.Type[] bounds = t.getBounds(); - for (int j = 0; j < bounds.length; j++) - { - sb.append(':').append(ToSigForm(bounds[j])); - } - } - sb.append('>'); - } - sb.append('('); - for (int i = 0; i < parameterTypes.length; i++) - { - java.lang.reflect.Type t = parameterTypes[i]; - isgeneric |= !(t instanceof Class); - sb.append(ToSigForm(t)); - } - sb.append(')'); - sb.append(ToSigForm(returnType)); - isgeneric |= !(returnType instanceof Class); - for (int i = 0; i < exceptionTypes.length; i++) - { - java.lang.reflect.Type t = exceptionTypes[i]; - isgeneric |= !(t instanceof Class); - sb.append('^').append(ToSigForm(t)); - } - if(isgeneric) - { - return sb.toString(); - } - return null; - } - - private static String ToSigForm(java.lang.reflect.Type t) - { - if(t instanceof java.lang.reflect.ParameterizedType) - { - java.lang.reflect.ParameterizedType p = (java.lang.reflect.ParameterizedType)t; - StringBuilder sb = new StringBuilder(); - sb.append('L').append(((Class)p.getRawType()).getName().replace('.', '/')); - sb.append('<'); - java.lang.reflect.Type[] args = p.getActualTypeArguments(); - for (int i = 0; i < args.length; i++) - { - sb.append(ToSigForm(args[i])); - } - sb.append(">;"); - return sb.toString(); - } - else if(t instanceof java.lang.reflect.TypeVariable) - { - return "T" + ((java.lang.reflect.TypeVariable)t).getName() + ";"; - } - else if(t instanceof java.lang.reflect.WildcardType) - { - java.lang.reflect.WildcardType w = (java.lang.reflect.WildcardType)t; - java.lang.reflect.Type[] lower = w.getLowerBounds(); - java.lang.reflect.Type[] upper = w.getUpperBounds(); - if (lower.length == 0 && upper.length == 0) - { - return "*"; - } - if (lower.length == 1) - { - return "-" + ToSigForm(lower[0]); - } - if (upper.length == 1) - { - return "+" + ToSigForm(upper[0]); - } - // TODO - throw new Error("Not Implemented"); - } - else if(t instanceof java.lang.reflect.GenericArrayType) - { - java.lang.reflect.GenericArrayType a = (java.lang.reflect.GenericArrayType)t; - return "[" + ToSigForm(a.getGenericComponentType()); - } - else if(t instanceof Class) - { - return ClassToSig((Class)t); - } - else - { - throw new Error("Not Implemented: " + t); - } - } -} - -class Modifiers -{ - static final short Public = 0x0001; - static final short Private = 0x0002; - static final short Protected = 0x0004; - static final short Static = 0x0008; - static final short Final = 0x0010; - static final short Super = 0x0020; - static final short Synchronized = 0x0020; - static final short Volatile = 0x0040; - static final short Bridge = 0x0040; - static final short Transient = 0x0080; - static final short VarArgs = 0x0080; - static final short Native = 0x0100; - static final short Interface = 0x0200; - static final short Abstract = 0x0400; - static final short Strictfp = 0x0800; - static final short Synthetic = 0x1000; - static final short Annotation = 0x2000; - static final short Enum = 0x4000; -} - -class Constant -{ - static final int Utf8 = 1; - static final int Integer = 3; - static final int Float = 4; - static final int Long = 5; - static final int Double = 6; - static final int Class = 7; - static final int String = 8; - static final int Fieldref = 9; - static final int Methodref = 10; - static final int InterfaceMethodref = 11; - static final int NameAndType = 12; -} - -abstract class ConstantPoolItem -{ - abstract void Write(DataOutputStream dos) throws IOException; -} - -final class ConstantPoolItemClass extends ConstantPoolItem -{ - private short name_index; - - public ConstantPoolItemClass(short name_index) - { - this.name_index = name_index; - } - - public int hashCode() - { - return name_index; - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemClass) - { - return ((ConstantPoolItemClass)o).name_index == name_index; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Class); - dos.writeShort(name_index); - } -} - -final class ConstantPoolItemMethodref extends ConstantPoolItem -{ - private short class_index; - private short name_and_type_index; - - public ConstantPoolItemMethodref(short class_index, short name_and_type_index) - { - this.class_index = class_index; - this.name_and_type_index = name_and_type_index; - } - - public int hashCode() - { - return (class_index & 0xFFFF) | (name_and_type_index << 16); - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemMethodref) - { - ConstantPoolItemMethodref m = (ConstantPoolItemMethodref)o; - return m.class_index == class_index && m.name_and_type_index == name_and_type_index; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Methodref); - dos.writeShort(class_index); - dos.writeShort(name_and_type_index); - } -} - -final class ConstantPoolItemNameAndType extends ConstantPoolItem -{ - private short name_index; - private short descriptor_index; - - public ConstantPoolItemNameAndType(short name_index, short descriptor_index) - { - this.name_index = name_index; - this.descriptor_index = descriptor_index; - } - - public int hashCode() - { - return (name_index & 0xFFFF) | (descriptor_index << 16); - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemNameAndType) - { - ConstantPoolItemNameAndType n = (ConstantPoolItemNameAndType)o; - return n.name_index == name_index && n.descriptor_index == descriptor_index; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.NameAndType); - dos.writeShort(name_index); - dos.writeShort(descriptor_index); - } -} - -final class ConstantPoolItemUtf8 extends ConstantPoolItem -{ - private String str; - - public ConstantPoolItemUtf8(String str) - { - this.str = str; - } - - public int hashCode() - { - return str.hashCode(); - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemUtf8) - { - return ((ConstantPoolItemUtf8)o).str.equals(str); - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Utf8); - dos.writeUTF(str); - } -} - -final class ConstantPoolItemInt extends ConstantPoolItem -{ - private int v; - - public ConstantPoolItemInt(int v) - { - this.v = v; - } - - public int hashCode() - { - return v; - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemInt) - { - return ((ConstantPoolItemInt)o).v == v; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Integer); - dos.writeInt(v); - } -} - -final class ConstantPoolItemLong extends ConstantPoolItem -{ - private long v; - - public ConstantPoolItemLong(long v) - { - this.v = v; - } - - public int hashCode() - { - return (int)v; - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemLong) - { - return ((ConstantPoolItemLong)o).v == v; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Long); - dos.writeLong(v); - } -} - -final class ConstantPoolItemFloat extends ConstantPoolItem -{ - private float v; - - public ConstantPoolItemFloat(float v) - { - this.v = v; - } - - public int hashCode() - { - return Float.floatToIntBits(v); - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemFloat) - { - return ((ConstantPoolItemFloat)o).v == v; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Float); - dos.writeFloat(v); - } -} - -final class ConstantPoolItemDouble extends ConstantPoolItem -{ - private double v; - - public ConstantPoolItemDouble(double v) - { - this.v = v; - } - - public int hashCode() - { - long l = Double.doubleToLongBits(v); - return ((int)l) ^ ((int)(l >> 32)); - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemDouble) - { - return ((ConstantPoolItemDouble)o).v == v; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.Double); - dos.writeDouble(v); - } -} - -final class ConstantPoolItemString extends ConstantPoolItem -{ - private short string_index; - - public ConstantPoolItemString(short string_index) - { - this.string_index = string_index; - } - - public int hashCode() - { - return string_index; - } - - public boolean equals(Object o) - { - if(o instanceof ConstantPoolItemString) - { - return ((ConstantPoolItemString)o).string_index == string_index; - } - return false; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeByte(Constant.String); - dos.writeShort(string_index); - } -} - -class ClassFileAttribute -{ - private short name_index; - - public ClassFileAttribute(short name_index) - { - this.name_index = name_index; - } - - void Write(DataOutputStream dos) throws IOException - { - dos.writeShort(name_index); - } -} - -class DeprecatedAttribute extends ClassFileAttribute -{ - DeprecatedAttribute(ClassFileWriter classFile) - { - super(classFile.AddUtf8("Deprecated")); - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(0); - } -} - -class ConstantValueAttribute extends ClassFileAttribute -{ - private short constant_index; - - public ConstantValueAttribute(short name_index, short constant_index) - { - super(name_index); - this.constant_index = constant_index; - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(2); - dos.writeShort(constant_index); - } -} - -class StringAttribute extends ClassFileAttribute -{ - private short string_index; - - public StringAttribute(short name_index, short string_index) - { - super(name_index); - this.string_index = string_index; - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(2); - dos.writeShort(string_index); - } -} - -class InnerClassesAttribute extends ClassFileAttribute -{ - private ClassFileWriter classFile; - private ArrayList classes = new ArrayList(); - - public InnerClassesAttribute(ClassFileWriter classFile) - { - super(classFile.AddUtf8("InnerClasses")); - this.classFile = classFile; - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(2 + 8 * classes.size()); - dos.writeShort(classes.size()); - for (int i = 0; i < classes.size(); i++) - { - Item it = (Item)classes.get(i); - dos.writeShort(it.inner_class_info_index); - dos.writeShort(it.outer_class_info_index); - dos.writeShort(it.inner_name_index); - dos.writeShort(it.inner_class_access_flags); - } - } - - private class Item - { - short inner_class_info_index; - short outer_class_info_index; - short inner_name_index; - short inner_class_access_flags; - } - - public void Add(String inner, String outer, String name, int access) - { - Item i = new Item(); - i.inner_class_info_index = classFile.AddClass(inner); - i.outer_class_info_index = classFile.AddClass(outer); - if(name != null) - { - i.inner_name_index = classFile.AddUtf8(name); - } - i.inner_class_access_flags = (short)access; - classes.add(i); - } -} - -class ExceptionsAttribute extends ClassFileAttribute -{ - private ClassFileWriter classFile; - private ArrayList classes = new ArrayList(); - - ExceptionsAttribute(ClassFileWriter classFile) - { - super(classFile.AddUtf8("Exceptions")); - this.classFile = classFile; - } - - void Add(String exceptionClass) - { - classes.add(classFile.AddClass(exceptionClass)); - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(2 + 2 * classes.size()); - dos.writeShort(classes.size()); - for (int i = 0; i < classes.size(); i++) - { - short idx = (Short)classes.get(i); - dos.writeShort(idx); - } - } -} - -class RuntimeVisibleAnnotationsAttribute extends ClassFileAttribute -{ - private ClassFileWriter classFile; - private byte[] buf; - - RuntimeVisibleAnnotationsAttribute(ClassFileWriter classFile, Annotation[] annotations) - { - super(classFile.AddUtf8("RuntimeVisibleAnnotations")); - this.classFile = classFile; - try - { - ByteArrayOutputStream mem = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(mem); - dos.writeShort((short)annotations.length); - for(Annotation ann : annotations) - { - WriteAnnotation(classFile, dos, ann); - } - buf = mem.toByteArray(); - } - catch(Exception x) - { - throw new Error(x); - } - } - - RuntimeVisibleAnnotationsAttribute(ClassFileWriter classFile, Annotation[][] parameterAnnotations) - { - super(classFile.AddUtf8("RuntimeVisibleParameterAnnotations")); - this.classFile = classFile; - try - { - ByteArrayOutputStream mem = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(mem); - dos.writeByte(parameterAnnotations.length); - for(Annotation[] annotations : parameterAnnotations) - { - dos.writeShort((short)annotations.length); - for(Annotation ann : annotations) - { - WriteAnnotation(classFile, dos, ann); - } - } - buf = mem.toByteArray(); - } - catch(Exception x) - { - throw new Error(x); - } - } - - private static boolean deepEquals(Object o1, Object o2) - { - if (o1 == o2) - return true; - - if (o1 == null || o2 == null) - return false; - - if (o1 instanceof boolean[] && o2 instanceof boolean[]) - return Arrays.equals((boolean[]) o1, (boolean[]) o2); - - if (o1 instanceof byte[] && o2 instanceof byte[]) - return Arrays.equals((byte[]) o1, (byte[]) o2); - - if (o1 instanceof char[] && o2 instanceof char[]) - return Arrays.equals((char[]) o1, (char[]) o2); - - if (o1 instanceof short[] && o2 instanceof short[]) - return Arrays.equals((short[]) o1, (short[]) o2); - - if (o1 instanceof int[] && o2 instanceof int[]) - return Arrays.equals((int[]) o1, (int[]) o2); - - if (o1 instanceof float[] && o2 instanceof float[]) - return Arrays.equals((float[]) o1, (float[]) o2); - - if (o1 instanceof long[] && o2 instanceof long[]) - return Arrays.equals((long[]) o1, (long[]) o2); - - if (o1 instanceof double[] && o2 instanceof double[]) - return Arrays.equals((double[]) o1, (double[]) o2); - - if (o1 instanceof Object[] && o2 instanceof Object[]) - return Arrays.equals((Object[]) o1, (Object[]) o2); - - return o1.equals(o2); - } - - static void WriteValue(ClassFileWriter classFile, DataOutputStream dos, Object val) - throws IOException, IllegalAccessException, InvocationTargetException - { - if(val instanceof Boolean) - { - dos.writeByte('Z'); - dos.writeShort(classFile.AddInt(((Boolean)val).booleanValue() ? 1 : 0)); - } - else if(val instanceof Byte) - { - dos.writeByte('B'); - dos.writeShort(classFile.AddInt(((Byte)val).byteValue())); - } - else if(val instanceof Character) - { - dos.writeByte('C'); - dos.writeShort(classFile.AddInt(((Character)val).charValue())); - } - else if(val instanceof Short) - { - dos.writeByte('S'); - dos.writeShort(classFile.AddInt(((Short)val).shortValue())); - } - else if(val instanceof Integer) - { - dos.writeByte('I'); - dos.writeShort(classFile.AddInt(((Integer)val).intValue())); - } - else if(val instanceof Float) - { - dos.writeByte('F'); - dos.writeShort(classFile.AddFloat(((Float)val).floatValue())); - } - else if(val instanceof Long) - { - dos.writeByte('J'); - dos.writeShort(classFile.AddLong(((Long)val).longValue())); - } - else if(val instanceof Double) - { - dos.writeByte('D'); - dos.writeShort(classFile.AddDouble(((Double)val).doubleValue())); - } - else if(val instanceof String) - { - dos.writeByte('s'); - dos.writeShort(classFile.AddUtf8((String)val)); - } - else if(val instanceof Enum) - { - Enum enumVal = (Enum)val; - Class enumType = enumVal.getDeclaringClass(); - dos.writeByte('e'); - dos.writeShort(classFile.AddUtf8("L" + enumType.getName().replace('.', '/') + ";")); - dos.writeShort(classFile.AddUtf8(enumVal.name())); - } - else if(val instanceof Class) - { - dos.writeByte('c'); - Class c = (Class)val; - String sig; - if(c.isArray()) - { - sig = c.getName(); - } - else if(c == Boolean.TYPE) - { - sig = "Z"; - } - else if(c == Byte.TYPE) - { - sig = "B"; - } - else if(c == Character.TYPE) - { - sig = "C"; - } - else if(c == Short.TYPE) - { - sig = "S"; - } - else if(c == Integer.TYPE) - { - sig = "I"; - } - else if(c == Float.TYPE) - { - sig = "F"; - } - else if(c == Long.TYPE) - { - sig = "J"; - } - else if(c == Double.TYPE) - { - sig = "D"; - } - else if(c == Void.TYPE) - { - sig = "V"; - } - else - { - sig = "L" + c.getName() + ";"; - } - dos.writeShort(classFile.AddUtf8(sig.replace('.', '/'))); - } - else if(val instanceof Annotation) - { - dos.writeByte('@'); - WriteAnnotation(classFile, dos, (Annotation)val); - } - else if(val.getClass().isArray()) - { - dos.writeByte('['); - int len = Array.getLength(val); - dos.writeShort((short)len); - for(int i = 0; i < len; i++) - { - WriteValue(classFile, dos, Array.get(val, i)); - } - } - else - { - throw new Error("Not Implemented: " + val.getClass()); - } - } - - static void WriteAnnotation(ClassFileWriter classFile, DataOutputStream dos, Annotation ann) - throws IOException, IllegalAccessException, InvocationTargetException - { - Class annotationType = ann.annotationType(); - dos.writeShort(classFile.AddUtf8("L" + annotationType.getName().replace('.', '/') + ";")); - short numvalues = 0; - Method[] methods = annotationType.getDeclaredMethods(); - for(int i = 0; i < methods.length; i++) - { - final Method m = methods[i]; - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - m.setAccessible(true); - return null; - } - }); - // HACK since there's no way to query if the annotation value is the default value - // (and I don't want to add a private API for that), we simply compare the value - // with the default and if they match we won't list the value. - if(deepEquals(m.invoke(ann), m.getDefaultValue())) - { - methods[i] = null; - } - else - { - numvalues++; - } - } - dos.writeShort(numvalues); - for(Method m : methods) - { - if(m != null) - { - dos.writeShort(classFile.AddUtf8(m.getName())); - WriteValue(classFile, dos, m.invoke(ann)); - } - } - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(buf.length); - dos.write(buf); - } -} - -class AnnotationDefaultClassFileAttribute extends ClassFileAttribute -{ - private ClassFileWriter classFile; - private byte[] buf; - - AnnotationDefaultClassFileAttribute(ClassFileWriter classFile, Object val) - { - super(classFile.AddUtf8("AnnotationDefault")); - this.classFile = classFile; - try - { - ByteArrayOutputStream mem = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(mem); - RuntimeVisibleAnnotationsAttribute.WriteValue(classFile, dos, val); - buf = mem.toByteArray(); - } - catch (Exception x) - { - throw new Error(x); - } - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(buf.length); - dos.write(buf); - } -} - -class FieldOrMethod -{ - private short access_flags; - private short name_index; - private short descriptor_index; - private ArrayList attribs = new ArrayList(); - - public FieldOrMethod(int access_flags, short name_index, short descriptor_index) - { - this.access_flags = (short)access_flags; - this.name_index = name_index; - this.descriptor_index = descriptor_index; - } - - public void AddAttribute(ClassFileAttribute attrib) - { - attribs.add(attrib); - } - - public void Write(DataOutputStream dos) throws IOException - { - dos.writeShort(access_flags); - dos.writeShort(name_index); - dos.writeShort(descriptor_index); - dos.writeShort(attribs.size()); - for(int i = 0; i < attribs.size(); i++) - { - ((ClassFileAttribute)attribs.get(i)).Write(dos); - } - } -} - -class CodeAttribute extends ClassFileAttribute -{ - private ClassFileWriter classFile; - private short max_stack; - private short max_locals; - private byte[] code; - - public CodeAttribute(ClassFileWriter classFile) - { - super(classFile.AddUtf8("Code")); - this.classFile = classFile; - } - - public void SetMaxStack(int v) - { - max_stack = (short)v; - } - - public void SetMaxLocals(int v) - { - max_locals = (short)v; - } - - public void SetByteCode(byte[] v) - { - code = v; - } - - void Write(DataOutputStream dos) throws IOException - { - super.Write(dos); - dos.writeInt(2 + 2 + 4 + code.length + 2 + 2); - dos.writeShort(max_stack); - dos.writeShort(max_locals); - dos.writeInt(code.length); - dos.write(code); - dos.writeShort(0); // no exceptions - dos.writeShort(0); // no attributes - } -} - -class ClassFileWriter -{ - private ArrayList cplist = new ArrayList(); - private Hashtable cphashtable = new Hashtable(); - private ArrayList fields = new ArrayList(); - private ArrayList methods = new ArrayList(); - private ArrayList attribs = new ArrayList(); - private ArrayList interfaces = new ArrayList(); - private int access_flags; - private short this_class; - private short super_class; - private short minorVersion; - private short majorVersion; - - public ClassFileWriter(int mods, String name, String superClass, int minorVersion, int majorVersion) - { - cplist.add(null); - access_flags = mods; - this_class = AddClass(name); - if(superClass != null) - { - super_class = AddClass(superClass); - } - this.minorVersion = (short)minorVersion; - this.majorVersion = (short)majorVersion; - } - - private short Add(ConstantPoolItem cpi) - { - Object index = cphashtable.get(cpi); - if(index == null) - { - index = (short)cplist.size(); - cplist.add(cpi); - if(cpi instanceof ConstantPoolItemDouble || cpi instanceof ConstantPoolItemLong) - { - cplist.add(null); - } - cphashtable.put(cpi, index); - } - return (Short)index; - } - - public short AddUtf8(String str) - { - return Add(new ConstantPoolItemUtf8(str)); - } - - public short AddClass(String classname) - { - return Add(new ConstantPoolItemClass(AddUtf8(classname))); - } - - public short AddMethodRef(String classname, String methodname, String signature) - { - return Add(new ConstantPoolItemMethodref(AddClass(classname), AddNameAndType(methodname, signature))); - } - - public short AddNameAndType(String name, String type) - { - return Add(new ConstantPoolItemNameAndType(AddUtf8(name), AddUtf8(type))); - } - - public short AddInt(int i) - { - return Add(new ConstantPoolItemInt(i)); - } - - public short AddLong(long l) - { - return Add(new ConstantPoolItemLong(l)); - } - - public short AddFloat(float f) - { - return Add(new ConstantPoolItemFloat(f)); - } - - public short AddDouble(double d) - { - return Add(new ConstantPoolItemDouble(d)); - } - - public short AddString(String s) - { - return Add(new ConstantPoolItemString(AddUtf8(s))); - } - - public void AddInterface(String name) - { - interfaces.add(AddClass(name)); - } - - public FieldOrMethod AddMethod(int access, String name, String signature) - { - FieldOrMethod method = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature)); - methods.add(method); - return method; - } - - public FieldOrMethod AddField(int access, String name, String signature, Object constantValue) - { - FieldOrMethod field = new FieldOrMethod(access, AddUtf8(name), AddUtf8(signature)); - if(constantValue != null) - { - short constantValueIndex; - if(constantValue instanceof Boolean) - { - constantValueIndex = AddInt(((Boolean)constantValue).booleanValue() ? 1 : 0); - } - else if(constantValue instanceof Byte) - { - constantValueIndex = AddInt(((Byte)constantValue).byteValue()); - } - else if(constantValue instanceof Short) - { - constantValueIndex = AddInt(((Short)constantValue).shortValue()); - } - else if(constantValue instanceof Character) - { - constantValueIndex = AddInt(((Character)constantValue).charValue()); - } - else if(constantValue instanceof Integer) - { - constantValueIndex = AddInt(((Integer)constantValue).intValue()); - } - else if(constantValue instanceof Long) - { - constantValueIndex = AddLong(((Long)constantValue).longValue()); - } - else if(constantValue instanceof Float) - { - constantValueIndex = AddFloat(((Float)constantValue).floatValue()); - } - else if(constantValue instanceof Double) - { - constantValueIndex = AddDouble(((Double)constantValue).doubleValue()); - } - else if(constantValue instanceof String) - { - constantValueIndex = AddString((String)constantValue); - } - else - { - throw new Error(); - } - field.AddAttribute(new ConstantValueAttribute(AddUtf8("ConstantValue"), constantValueIndex)); - } - fields.add(field); - return field; - } - - public ClassFileAttribute MakeStringAttribute(String name, String value) - { - return new StringAttribute(AddUtf8(name), AddUtf8(value)); - } - - public void AddStringAttribute(String name, String value) - { - attribs.add(MakeStringAttribute(name, value)); - } - - public void AddAttribute(ClassFileAttribute attrib) - { - attribs.add(attrib); - } - - public void Write(OutputStream stream) throws IOException - { - DataOutputStream dos = new DataOutputStream(stream); - dos.writeInt(0xCAFEBABE); - dos.writeShort(minorVersion); - dos.writeShort(majorVersion); - dos.writeShort(cplist.size()); - for(int i = 1; i < cplist.size(); i++) - { - ConstantPoolItem cpi = (ConstantPoolItem)cplist.get(i); - if(cpi != null) - { - cpi.Write(dos); - } - } - dos.writeShort(access_flags); - dos.writeShort(this_class); - dos.writeShort(super_class); - // interfaces count - dos.writeShort(interfaces.size()); - for(int i = 0; i < interfaces.size(); i++) - { - dos.writeShort((Short)interfaces.get(i)); - } - // fields count - dos.writeShort(fields.size()); - for(int i = 0; i < fields.size(); i++) - { - ((FieldOrMethod)fields.get(i)).Write(dos); - } - // methods count - dos.writeShort(methods.size()); - for(int i = 0; i < methods.size(); i++) - { - ((FieldOrMethod)methods.get(i)).Write(dos); - } - // attributes count - dos.writeShort(attribs.size()); - for(int i = 0; i < attribs.size(); i++) - { - ((ClassFileAttribute)attribs.get(i)).Write(dos); - } - } -} diff --git a/ikvmstub/ikvmstub.8.csproj b/ikvmstub/ikvmstub.8.csproj index 822c2c2b..b1998f93 100644 --- a/ikvmstub/ikvmstub.8.csproj +++ b/ikvmstub/ikvmstub.8.csproj @@ -68,7 +68,7 @@ <Compile Include="AssemblyInfo.cs"> <SubType>Code</SubType> </Compile> - <Compile Include="ClassFileWriter.cs" /> + <Compile Include="..\runtime\stubgen\ClassFileWriter.cs" /> <Compile Include="ikvmstub.cs"> <SubType>Code</SubType> </Compile> @@ -102,7 +102,8 @@ <Compile Include="..\runtime\vm.cs"> <SubType>Code</SubType> </Compile> - <Compile Include="SerialVersionUID.cs" /> + <Compile Include="..\runtime\stubgen\SerialVersionUID.cs" /> + <Compile Include="..\runtime\stubgen\StubGenerator.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\reflect\IKVM.Reflection.csproj"> diff --git a/ikvmstub/ikvmstub.build b/ikvmstub/ikvmstub.build index 02cd5342..8a829630 100644 --- a/ikvmstub/ikvmstub.build +++ b/ikvmstub/ikvmstub.build @@ -24,10 +24,11 @@ <include name="../runtime/Types.cs" /> <include name="../runtime/TypeWrapper.cs" /> <include name="../runtime/vm.cs" /> + <include name="../runtime/stubgen/ClassFileWriter.cs" /> + <include name="../runtime/stubgen/SerialVersionUID.cs" /> + <include name="../runtime/stubgen/StubGenerator.cs" /> <include name="AssemblyInfo.cs" /> - <include name="ClassFileWriter.cs" /> <include name="ikvmstub.cs" /> - <include name="SerialVersionUID.cs" /> </sources> <references> <include name="../bin/ICSharpCode.SharpZipLib.dll" asis="true" /> diff --git a/ikvmstub/ikvmstub.cs b/ikvmstub/ikvmstub.cs index e7f70d37..71446c9d 100644 --- a/ikvmstub/ikvmstub.cs +++ b/ikvmstub/ikvmstub.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2012 Jeroen Frijters + Copyright (C) 2002-2013 Jeroen Frijters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -321,469 +321,15 @@ static class NetExp private static void WriteClass(TypeWrapper tw) { - string name = tw.Name.Replace('.', '/'); - string super = null; - if (tw.IsInterface) - { - super = "java/lang/Object"; - } - else if (tw.BaseTypeWrapper != null) - { - super = tw.BaseTypeWrapper.Name.Replace('.', '/'); - } - IKVM.StubGen.ClassFileWriter writer = new IKVM.StubGen.ClassFileWriter(tw.Modifiers, name, super, 0, 49); - foreach (TypeWrapper iface in tw.Interfaces) - { - if (iface.IsPublic || includeNonPublicInterfaces) - { - writer.AddInterface(iface.Name.Replace('.', '/')); - } - } - IKVM.StubGen.InnerClassesAttribute innerClassesAttribute = null; - if (tw.DeclaringTypeWrapper != null) - { - TypeWrapper outer = tw.DeclaringTypeWrapper; - string innername = name; - int idx = name.LastIndexOf('$'); - if (idx >= 0) - { - innername = innername.Substring(idx + 1); - } - innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer); - innerClassesAttribute.Add(name, outer.Name.Replace('.', '/'), innername, (ushort)tw.ReflectiveModifiers); - } - foreach (TypeWrapper inner in tw.InnerClasses) - { - if (inner.IsPublic) - { - if (innerClassesAttribute == null) - { - innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer); - } - string namePart = inner.Name; - namePart = namePart.Substring(namePart.LastIndexOf('$') + 1); - innerClassesAttribute.Add(inner.Name.Replace('.', '/'), name, namePart, (ushort)inner.ReflectiveModifiers); - } - } - if (innerClassesAttribute != null) - { - writer.AddAttribute(innerClassesAttribute); - } - string genericTypeSignature = tw.GetGenericSignature(); - if (genericTypeSignature != null) - { - writer.AddStringAttribute("Signature", genericTypeSignature); - } - writer.AddStringAttribute("IKVM.NET.Assembly", GetAssemblyName(tw)); - if (tw.TypeAsBaseType.IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false)) - { - writer.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); - } - foreach (MethodWrapper mw in tw.GetMethods()) - { - if (!mw.IsHideFromReflection && (mw.IsPublic || mw.IsProtected || includeNonPublicMembers)) - { - IKVM.StubGen.FieldOrMethod m; - if (mw.Name == "<init>") - { - m = writer.AddMethod(mw.Modifiers, mw.Name, mw.Signature.Replace('.', '/')); - IKVM.StubGen.CodeAttribute code = new IKVM.StubGen.CodeAttribute(writer); - code.MaxLocals = (ushort)(mw.GetParameters().Length * 2 + 1); - code.MaxStack = 3; - ushort index1 = writer.AddClass("java/lang/UnsatisfiedLinkError"); - ushort index2 = writer.AddString("ikvmstub generated stubs can only be used on IKVM.NET"); - ushort index3 = writer.AddMethodRef("java/lang/UnsatisfiedLinkError", "<init>", "(Ljava/lang/String;)V"); - code.ByteCode = new byte[] { - 187, (byte)(index1 >> 8), (byte)index1, // new java/lang/UnsatisfiedLinkError - 89, // dup - 19, (byte)(index2 >> 8), (byte)index2, // ldc_w "..." - 183, (byte)(index3 >> 8), (byte)index3, // invokespecial java/lang/UnsatisfiedLinkError/init()V - 191 // athrow - }; - m.AddAttribute(code); - } - else - { - Modifiers mods = mw.Modifiers; - if ((mods & Modifiers.Abstract) == 0) - { - mods |= Modifiers.Native; - } - m = writer.AddMethod(mods, mw.Name, mw.Signature.Replace('.', '/')); - if (mw.IsOptionalAttributeAnnotationValue) - { - m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, mw.ReturnType))); - } - } - MethodBase mb = mw.GetMethod(); - if (mb != null) - { - ThrowsAttribute throws = AttributeHelper.GetThrows(mb); - if (throws == null) - { - string[] throwsArray = mw.GetDeclaredExceptions(); - if (throwsArray != null && throwsArray.Length > 0) - { - IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer); - foreach (string ex in throwsArray) - { - attrib.Add(ex.Replace('.', '/')); - } - m.AddAttribute(attrib); - } - } - else - { - IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer); - if (throws.classes != null) - { - foreach (string ex in throws.classes) - { - attrib.Add(ex.Replace('.', '/')); - } - } - if (throws.types != null) - { - foreach (Type ex in throws.types) - { - attrib.Add(ClassLoaderWrapper.GetWrapperFromType(ex).Name.Replace('.', '/')); - } - } - m.AddAttribute(attrib); - } - if (mb.IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false) - // HACK the instancehelper methods are marked as Obsolete (to direct people toward the ikvm.extensions methods instead) - // but in the Java world most of them are not deprecated (and to keep the Japi results clean we need to reflect this) - && (!mb.Name.StartsWith("instancehelper_") - || mb.DeclaringType.FullName != "java.lang.String" - // the Java deprecated methods actually have two Obsolete attributes - || mb.__GetCustomAttributes(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false).Count == 2)) - { - m.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); - } - IList<CustomAttributeData> attr = CustomAttributeData.__GetCustomAttributes(mb, JVM.LoadType(typeof(AnnotationDefaultAttribute)), false); - if (attr.Count == 1) - { - m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, attr[0].ConstructorArguments[0]))); - } - } - string sig = tw.GetGenericMethodSignature(mw); - if (sig != null) - { - m.AddAttribute(writer.MakeStringAttribute("Signature", sig)); - } - } - } - bool hasSerialVersionUID = false; - foreach (FieldWrapper fw in tw.GetFields()) - { - if (!fw.IsHideFromReflection) - { - bool isSerialVersionUID = includeSerialVersionUID && fw.Name == "serialVersionUID" && fw.FieldTypeWrapper == PrimitiveTypeWrapper.LONG; - hasSerialVersionUID |= isSerialVersionUID; - if (fw.IsPublic || fw.IsProtected || isSerialVersionUID || includeNonPublicMembers) - { - object constant = null; - if (fw.GetField() != null && fw.GetField().IsLiteral && (fw.FieldTypeWrapper.IsPrimitive || fw.FieldTypeWrapper == CoreClasses.java.lang.String.Wrapper)) - { - constant = fw.GetField().GetRawConstantValue(); - if (fw.GetField().FieldType.IsEnum) - { - constant = EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(fw.GetField().FieldType), constant); - } - } - IKVM.StubGen.FieldOrMethod f = writer.AddField(fw.Modifiers, fw.Name, fw.Signature.Replace('.', '/'), constant); - string sig = tw.GetGenericFieldSignature(fw); - if (sig != null) - { - f.AddAttribute(writer.MakeStringAttribute("Signature", sig)); - } - if (fw.GetField() != null && fw.GetField().IsDefined(StaticCompiler.Universe.Import(typeof(ObsoleteAttribute)), false)) - { - f.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); - } - } - } - } - if (includeSerialVersionUID && !hasSerialVersionUID && IsSerializable(tw)) - { - // class is serializable but doesn't have an explicit serialVersionUID, so we add the field to record - // the serialVersionUID as we see it (mainly to make the Japi reports more realistic) - writer.AddField(Modifiers.Private | Modifiers.Static | Modifiers.Final, "serialVersionUID", "J", IKVM.StubGen.SerialVersionUID.Compute(tw)); - } - AddMetaAnnotations(writer, tw); zipCount++; MemoryStream mem = new MemoryStream(); - writer.Write(mem); - ZipEntry entry = new ZipEntry(name + ".class"); + IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, includeNonPublicMembers, includeSerialVersionUID); + ZipEntry entry = new ZipEntry(tw.Name.Replace('.', '/') + ".class"); entry.Size = mem.Position; zipFile.PutNextEntry(entry); mem.WriteTo(zipFile); } - private static string GetAssemblyName(TypeWrapper tw) - { - ClassLoaderWrapper loader = tw.GetClassLoader(); - AssemblyClassLoader acl = loader as AssemblyClassLoader; - if (acl != null) - { - return acl.GetAssembly(tw).FullName; - } - else - { - return ((GenericClassLoaderWrapper)loader).GetName(); - } - } - - private static bool IsSerializable(TypeWrapper tw) - { - if (tw.Name == "java.io.Serializable") - { - return true; - } - while (tw != null) - { - foreach (TypeWrapper iface in tw.Interfaces) - { - if (IsSerializable(iface)) - { - return true; - } - } - tw = tw.BaseTypeWrapper; - } - return false; - } - - private static void AddMetaAnnotations(IKVM.StubGen.ClassFileWriter writer, TypeWrapper tw) - { - DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase attributeAnnotation = tw as DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase; - if (attributeAnnotation != null) - { - // TODO write the annotation directly, instead of going thru the object[] encoding - IKVM.StubGen.RuntimeVisibleAnnotationsAttribute annot = new IKVM.StubGen.RuntimeVisibleAnnotationsAttribute(writer); - annot.Add(new object[] { - AnnotationDefaultAttribute.TAG_ANNOTATION, - "Ljava/lang/annotation/Retention;", - "value", - new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME" } - }); - AttributeTargets validOn = attributeAnnotation.AttributeTargets; - List<object[]> targets = new List<object[]>(); - if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0) - { - targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "TYPE" }); - } - if ((validOn & AttributeTargets.Constructor) != 0) - { - targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "CONSTRUCTOR" }); - } - if ((validOn & AttributeTargets.Field) != 0) - { - targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "FIELD" }); - } - if ((validOn & (AttributeTargets.Method | AttributeTargets.ReturnValue)) != 0) - { - targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "METHOD" }); - } - if ((validOn & AttributeTargets.Parameter) != 0) - { - targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "PARAMETER" }); - } - annot.Add(new object[] { - AnnotationDefaultAttribute.TAG_ANNOTATION, - "Ljava/lang/annotation/Target;", - "value", - new object[] { AnnotationDefaultAttribute.TAG_ARRAY, targets.ToArray() } - }); - writer.AddAttribute(annot); - } - } - - private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, TypeWrapper type) - { - MemoryStream mem = new MemoryStream(); - IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem); - if (type == PrimitiveTypeWrapper.BOOLEAN) - { - bes.WriteByte((byte)'Z'); - bes.WriteUInt16(classFile.AddInt(0)); - } - else if(type == PrimitiveTypeWrapper.BYTE) - { - bes.WriteByte((byte)'B'); - bes.WriteUInt16(classFile.AddInt(0)); - } - else if(type == PrimitiveTypeWrapper.CHAR) - { - bes.WriteByte((byte)'C'); - bes.WriteUInt16(classFile.AddInt(0)); - } - else if(type == PrimitiveTypeWrapper.SHORT) - { - bes.WriteByte((byte)'S'); - bes.WriteUInt16(classFile.AddInt(0)); - } - else if(type == PrimitiveTypeWrapper.INT) - { - bes.WriteByte((byte)'I'); - bes.WriteUInt16(classFile.AddInt(0)); - } - else if(type == PrimitiveTypeWrapper.FLOAT) - { - bes.WriteByte((byte)'F'); - bes.WriteUInt16(classFile.AddFloat(0)); - } - else if(type == PrimitiveTypeWrapper.LONG) - { - bes.WriteByte((byte)'J'); - bes.WriteUInt16(classFile.AddLong(0)); - } - else if (type == PrimitiveTypeWrapper.DOUBLE) - { - bes.WriteByte((byte)'D'); - bes.WriteUInt16(classFile.AddDouble(0)); - } - else if (type == CoreClasses.java.lang.String.Wrapper) - { - bes.WriteByte((byte)'s'); - bes.WriteUInt16(classFile.AddUtf8("")); - } - else if ((type.Modifiers & Modifiers.Enum) != 0) - { - bes.WriteByte((byte)'e'); - bes.WriteUInt16(classFile.AddUtf8("L" + type.Name.Replace('.', '/') + ";")); - bes.WriteUInt16(classFile.AddUtf8("__unspecified")); - } - else if (type == CoreClasses.java.lang.Class.Wrapper) - { - bes.WriteByte((byte)'c'); - bes.WriteUInt16(classFile.AddUtf8("Likvm/internal/__unspecified;")); - } - else if (type.IsArray) - { - bes.WriteByte((byte)'['); - bes.WriteUInt16(0); - } - else - { - throw new InvalidOperationException(); - } - return mem.ToArray(); - } - - private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, CustomAttributeTypedArgument value) - { - MemoryStream mem = new MemoryStream(); - IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem); - try - { - WriteAnnotationElementValue(classFile, bes, value); - } - catch (InvalidCastException) - { - Console.Error.WriteLine("Warning: incorrect annotation default value"); - } - catch (IndexOutOfRangeException) - { - Console.Error.WriteLine("Warning: incorrect annotation default value"); - } - return mem.ToArray(); - } - - private static void WriteAnnotationElementValue(IKVM.StubGen.ClassFileWriter classFile, IKVM.StubGen.BigEndianStream bes, CustomAttributeTypedArgument value) - { - if (value.ArgumentType == Types.Boolean) - { - bes.WriteByte((byte)'Z'); - bes.WriteUInt16(classFile.AddInt((bool)value.Value ? 1 : 0)); - } - else if (value.ArgumentType == Types.Byte) - { - bes.WriteByte((byte)'B'); - bes.WriteUInt16(classFile.AddInt((byte)value.Value)); - } - else if (value.ArgumentType == Types.Char) - { - bes.WriteByte((byte)'C'); - bes.WriteUInt16(classFile.AddInt((char)value.Value)); - } - else if (value.ArgumentType == Types.Int16) - { - bes.WriteByte((byte)'S'); - bes.WriteUInt16(classFile.AddInt((short)value.Value)); - } - else if (value.ArgumentType == Types.Int32) - { - bes.WriteByte((byte)'I'); - bes.WriteUInt16(classFile.AddInt((int)value.Value)); - } - else if (value.ArgumentType == Types.Single) - { - bes.WriteByte((byte)'F'); - bes.WriteUInt16(classFile.AddFloat((float)value.Value)); - } - else if (value.ArgumentType == Types.Int64) - { - bes.WriteByte((byte)'J'); - bes.WriteUInt16(classFile.AddLong((long)value.Value)); - } - else if (value.ArgumentType == Types.Double) - { - bes.WriteByte((byte)'D'); - bes.WriteUInt16(classFile.AddDouble((double)value.Value)); - } - else if (value.ArgumentType == Types.String) - { - bes.WriteByte((byte)'s'); - bes.WriteUInt16(classFile.AddUtf8((string)value.Value)); - } - else if (value.ArgumentType == Types.Object.MakeArrayType()) - { - CustomAttributeTypedArgument[] array = (CustomAttributeTypedArgument[])value.Value; - byte type = (byte)array[0].Value; - if (type == AnnotationDefaultAttribute.TAG_ARRAY) - { - bes.WriteByte((byte)'['); - bes.WriteUInt16((ushort)(array.Length - 1)); - for (int i = 1; i < array.Length; i++) - { - WriteAnnotationElementValue(classFile, bes, array[i]); - } - } - else if (type == AnnotationDefaultAttribute.TAG_CLASS) - { - bes.WriteByte((byte)'c'); - bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); - } - else if (type == AnnotationDefaultAttribute.TAG_ENUM) - { - bes.WriteByte((byte)'e'); - bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); - bes.WriteUInt16(classFile.AddUtf8((string)array[2].Value)); - } - else if (type == AnnotationDefaultAttribute.TAG_ANNOTATION) - { - bes.WriteByte((byte)'@'); - bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); - bes.WriteUInt16((ushort)((array.Length - 2) / 2)); - for (int i = 2; i < array.Length; i += 2) - { - bes.WriteUInt16(classFile.AddUtf8((string)array[i].Value)); - WriteAnnotationElementValue(classFile, bes, array[i + 1]); - } - } - else - { - Console.Error.WriteLine("Warning: incorrect annotation default element tag: " + type); - } - } - else - { - Console.Error.WriteLine("Warning: incorrect annotation default element type: " + value.ArgumentType); - } - } - private static bool ExportNamespace(Type type) { if (namespaces.Count == 0) diff --git a/openjdk/allsources.lst b/openjdk/allsources.lst index b3b62f30..5df16cb5 100644 --- a/openjdk/allsources.lst +++ b/openjdk/allsources.lst @@ -7,7 +7,6 @@ ../classpath/ikvm/internal/HasCallerID.java ../classpath/ikvm/internal/JMath.java ../classpath/ikvm/internal/MonoUtils.java -../classpath/ikvm/internal/stubgen/StubGenerator.java ../classpath/ikvm/internal/Util.java ../classpath/ikvm/internal/WeakIdentityMap.java ../classpath/ikvm/io/InputStreamWrapper.java diff --git a/openjdk/response.txt b/openjdk/response.txt index 0aa4d190..9dca1438 100644 --- a/openjdk/response.txt +++ b/openjdk/response.txt @@ -55,7 +55,6 @@ assembly.class ../classpath/gnu/java/net/protocol/ikvmres/*.class ../classpath/ikvm/extensions/*.class ../classpath/ikvm/internal/*.class - ../classpath/ikvm/internal/stubgen/*.class ../classpath/ikvm/io/*.class ../classpath/ikvm/lang/*.class ../classpath/ikvm/runtime/*.class @@ -168,7 +167,7 @@ assembly.class } { -out:IKVM.OpenJDK.Corba.dll - -baseaddress:0x56C90000 + -baseaddress:0x56C60000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/corba/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/jndi/cosnaming/jndiprovider.properties @OPENJDK7@/build/linux-amd64/impsrc/com/sun/corba/se/impl/activation/*.class @@ -286,7 +285,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.API.dll - -baseaddress:0x572F0000 + -baseaddress:0x572C0000 @OPENJDK7@/build/linux-amd64/impsrc/javax/xml/*.class @OPENJDK7@/build/linux-amd64/impsrc/javax/xml/datatype/*.class @OPENJDK7@/build/linux-amd64/impsrc/javax/xml/namespace/*.class @@ -319,7 +318,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.XPath.dll - -baseaddress:0x573B0000 + -baseaddress:0x57380000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/org/apache/xalan/internal/res/* @OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/xalan/internal/extensions/*.class @OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/xalan/internal/res/*.class @@ -344,7 +343,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.Parse.dll - -baseaddress:0x57710000 + -baseaddress:0x576E0000 -resource:com/sun/org/apache/xml/internal/serialize/HTMLEntities.res=@OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/xml/internal/serialize/HTMLEntities.res -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/org/apache/xerces/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/org/apache/xml/internal/serializer/* @@ -405,7 +404,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.Transform.dll - -baseaddress:0x57EC0000 + -baseaddress:0x57E90000 @OPENJDK7@/build/linux-amd64/impsrc/com/sun/java_cup/internal/runtime/*.class @OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/bcel/internal/*.class @OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/bcel/internal/classfile/*.class @@ -429,7 +428,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.Bind.dll - -baseaddress:0x58310000 + -baseaddress:0x582E0000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/javax/xml/bind/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/bind/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/fastinfoset/* @@ -488,7 +487,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.WebServices.dll - -baseaddress:0x586A0000 + -baseaddress:0x58670000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/messaging/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/ws/* @OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/glassfish/external/amx/*.class @@ -608,7 +607,7 @@ assembly.class } { -out:IKVM.OpenJDK.XML.Crypto.dll - -baseaddress:0x58C10000 + -baseaddress:0x58BE0000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/org/apache/xml/internal/security/* @OPENJDK7@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/*.class @OPENJDK7@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/*.class @@ -644,7 +643,7 @@ assembly.class } { -out:IKVM.OpenJDK.SwingAWT.dll - -baseaddress:0x58D60000 + -baseaddress:0x58D30000 -remap:swingawt.xml -resource:META-INF/services/sun.java2d.pipe.RenderingEngine=resources/META-INF/services/sun.java2d.pipe.RenderingEngine -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/sun.java2d.cmm.PCMM @@ -744,7 +743,7 @@ assembly.class } { -out:IKVM.OpenJDK.Charsets.dll - -baseaddress:0x59F60000 + -baseaddress:0x59F30000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/charsets.jar/sun/nio/cs/ext/sjis0213.dat -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/charsets.jar/META-INF/services/java.nio.charset.spi.CharsetProvider @OPENJDK7@/build/linux-amd64/gensrc/sun/nio/cs/ext/*.class @@ -753,7 +752,7 @@ assembly.class } { -out:IKVM.OpenJDK.Util.dll - -baseaddress:0x5A5F0000 + -baseaddress:0x5A5C0000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/java/util/jar/pack/intrinsic.properties -recurse:resources.zip/sun/launcher/resources/* -resource:META-INF/services/java.nio.file.spi.FileSystemProvider=@OPENJDK7@/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider @@ -776,7 +775,7 @@ assembly.class } { -out:IKVM.OpenJDK.Text.dll - -baseaddress:0x5ABC0000 + -baseaddress:0x5AB90000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/sun/text/* @OPENJDK7@/build/linux-amd64/j2re-image/lib/ext/localedata.jar @OPENJDK7@/jdk/src/share/classes/java/text/*.class @@ -788,7 +787,7 @@ assembly.class } { -out:IKVM.OpenJDK.Security.dll - -baseaddress:0x5AE30000 + -baseaddress:0x5AE00000 -remap:security.xml sun/security/jgss/wrapper/*.class @OPENJDK7@/jdk/src/share/classes/com/sun/crypto/provider/*.class @@ -859,7 +858,7 @@ assembly.class } { -out:IKVM.OpenJDK.Management.dll - -baseaddress:0x5B640000 + -baseaddress:0x5B610000 com/sun/management/*.class java/lang/management/*.class sun/management/*.class @@ -893,7 +892,7 @@ assembly.class } { -out:IKVM.OpenJDK.Misc.dll - -baseaddress:0x5B9A0000 + -baseaddress:0x5B970000 -resource:com/sun/servicetag/resources/javase_5_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties -resource:com/sun/servicetag/resources/javase_6_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties -resource:com/sun/servicetag/resources/javase_7_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties @@ -994,7 +993,7 @@ assembly.class } { -out:IKVM.OpenJDK.Naming.dll - -baseaddress:0x5BAC0000 + -baseaddress:0x5BA90000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/jndi/ldap/jndiprovider.properties -resource:META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor=@OPENJDK7@/jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor sun/net/dns/*.class @@ -1020,7 +1019,7 @@ assembly.class } { -out:IKVM.OpenJDK.Jdbc.dll - -baseaddress:0x5BC10000 + -baseaddress:0x5BBE0000 -resource:META-INF/services/java.sql.Driver=resources/META-INF/services/java.sql.Driver -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/rowset/* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/javax/sql/* @@ -1038,7 +1037,7 @@ assembly.class } { -out:IKVM.OpenJDK.Remoting.dll - -baseaddress:0x5BD60000 + -baseaddress:0x5BD30000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/sun/rmi/* @OPENJDK7@/build/linux-amd64/classes/sun/rmi/registry/*.class @OPENJDK7@/build/linux-amd64/classes/sun/rmi/server/*.class @@ -1064,7 +1063,7 @@ assembly.class } { -out:IKVM.OpenJDK.Beans.dll - -baseaddress:0x5BE80000 + -baseaddress:0x5BE50000 @OPENJDK7@/build/linux-amd64/impsrc/com/sun/activation/registries/*.class @OPENJDK7@/build/linux-amd64/impsrc/javax/activation/*.class @OPENJDK7@/jdk/src/share/classes/com/sun/beans/*.class @@ -1077,7 +1076,7 @@ assembly.class } { -out:IKVM.OpenJDK.Media.dll - -baseaddress:0x5BF40000 + -baseaddress:0x5BF10000 -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/javax.print.* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/javax.sound.* -recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/imageio/plugins/common/iio-plugin.properties diff --git a/runtime/IKVM.Runtime.8.csproj b/runtime/IKVM.Runtime.8.csproj index 5709b830..15f4814c 100644 --- a/runtime/IKVM.Runtime.8.csproj +++ b/runtime/IKVM.Runtime.8.csproj @@ -157,6 +157,9 @@ <Compile Include="ReflectUtil.cs" /> <Compile Include="RuntimeHelperTypes.cs" /> <Compile Include="Serialization.cs" /> + <Compile Include="stubgen\ClassFileWriter.cs" /> + <Compile Include="stubgen\SerialVersionUID.cs" /> + <Compile Include="stubgen\StubGenerator.cs" /> <Compile Include="tracer.cs"> <SubType>Code</SubType> </Compile> diff --git a/runtime/common.cs b/runtime/common.cs index 3076ad90..19dfc7ae 100644 --- a/runtime/common.cs +++ b/runtime/common.cs @@ -44,6 +44,16 @@ namespace IKVM.NativeCode.gnu.java.net.protocol.ikvmres { static class Handler { + public static byte[] GenerateStub(jlClass c) + { + MemoryStream mem = new MemoryStream(); +#if !FIRST_PASS + bool includeNonPublicInterfaces = !"true".Equals(global::java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase); + IKVM.StubGen.StubGenerator.WriteClass(mem, TypeWrapper.FromClass(c), includeNonPublicInterfaces, false, false); +#endif + return mem.ToArray(); + } + public static Stream ReadResourceFromAssemblyImpl(Assembly asm, string resource) { // chop off the leading slash diff --git a/runtime/openjdk.cs b/runtime/openjdk.cs index d3cc9d34..c1fe52d4 100644 --- a/runtime/openjdk.cs +++ b/runtime/openjdk.cs @@ -89,7 +89,6 @@ using srFieldAccessor = sun.reflect.FieldAccessor; using srLangReflectAccess = sun.reflect.LangReflectAccess; using srReflection = sun.reflect.Reflection; using srReflectionFactory = sun.reflect.ReflectionFactory; -using StubGenerator = ikvm.@internal.stubgen.StubGenerator; using Annotation = java.lang.annotation.Annotation; using smJavaIOAccess = sun.misc.JavaIOAccess; using smLauncher = sun.misc.Launcher; diff --git a/runtime/runtime.build b/runtime/runtime.build index ab53b85b..96e1bb2a 100644 --- a/runtime/runtime.build +++ b/runtime/runtime.build @@ -155,6 +155,9 @@ <include name="openjdk/sun.management.cs" /> <include name="openjdk/sun.nio.ch.cs" /> <include name="openjdk/sun.security.krb5.cs" /> + <include name="stubgen/ClassFileWriter.cs" /> + <include name="stubgen/SerialVersionUID.cs" /> + <include name="stubgen/StubGenerator.cs" /> </sources> <resources> <include if="${not first-pass}" name="../openjdk/vfs.zip" /> diff --git a/ikvmstub/ClassFileWriter.cs b/runtime/stubgen/ClassFileWriter.cs index 197746ac..197746ac 100644 --- a/ikvmstub/ClassFileWriter.cs +++ b/runtime/stubgen/ClassFileWriter.cs diff --git a/ikvmstub/SerialVersionUID.cs b/runtime/stubgen/SerialVersionUID.cs index 255a0ff8..fc972d28 100644 --- a/ikvmstub/SerialVersionUID.cs +++ b/runtime/stubgen/SerialVersionUID.cs @@ -27,7 +27,9 @@ using System.IO; using System.Text; using IKVM.Attributes; using IKVM.Internal; +#if STUB_GENERATOR using Type = IKVM.Reflection.Type; +#endif namespace IKVM.StubGen { diff --git a/runtime/stubgen/StubGenerator.cs b/runtime/stubgen/StubGenerator.cs new file mode 100644 index 00000000..99378d7f --- /dev/null +++ b/runtime/stubgen/StubGenerator.cs @@ -0,0 +1,525 @@ +/* + Copyright (C) 2002-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jeroen Frijters + jeroen@frijters.net + +*/ +using System; +using System.IO; +using System.Collections.Generic; +#if STUB_GENERATOR +using IKVM.Reflection; +using Type = IKVM.Reflection.Type; +#else +using System.Reflection; +#endif +using IKVM.Attributes; +using IKVM.Internal; + +namespace IKVM.StubGen +{ + static class StubGenerator + { + internal static void WriteClass(Stream stream, TypeWrapper tw, bool includeNonPublicInterfaces, bool includeNonPublicMembers, bool includeSerialVersionUID) + { + string name = tw.Name.Replace('.', '/'); + string super = null; + if (tw.IsInterface) + { + super = "java/lang/Object"; + } + else if (tw.BaseTypeWrapper != null) + { + super = tw.BaseTypeWrapper.Name.Replace('.', '/'); + } + IKVM.StubGen.ClassFileWriter writer = new IKVM.StubGen.ClassFileWriter(tw.Modifiers, name, super, 0, 49); + foreach (TypeWrapper iface in tw.Interfaces) + { + if (iface.IsPublic || includeNonPublicInterfaces) + { + writer.AddInterface(iface.Name.Replace('.', '/')); + } + } + IKVM.StubGen.InnerClassesAttribute innerClassesAttribute = null; + if (tw.DeclaringTypeWrapper != null) + { + TypeWrapper outer = tw.DeclaringTypeWrapper; + string innername = name; + int idx = name.LastIndexOf('$'); + if (idx >= 0) + { + innername = innername.Substring(idx + 1); + } + innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer); + innerClassesAttribute.Add(name, outer.Name.Replace('.', '/'), innername, (ushort)tw.ReflectiveModifiers); + } + foreach (TypeWrapper inner in tw.InnerClasses) + { + if (inner.IsPublic) + { + if (innerClassesAttribute == null) + { + innerClassesAttribute = new IKVM.StubGen.InnerClassesAttribute(writer); + } + string namePart = inner.Name; + namePart = namePart.Substring(namePart.LastIndexOf('$') + 1); + innerClassesAttribute.Add(inner.Name.Replace('.', '/'), name, namePart, (ushort)inner.ReflectiveModifiers); + } + } + if (innerClassesAttribute != null) + { + writer.AddAttribute(innerClassesAttribute); + } + string genericTypeSignature = tw.GetGenericSignature(); + if (genericTypeSignature != null) + { + writer.AddStringAttribute("Signature", genericTypeSignature); + } + writer.AddStringAttribute("IKVM.NET.Assembly", GetAssemblyName(tw)); + if (tw.TypeAsBaseType.IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false)) + { + writer.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); + } + foreach (MethodWrapper mw in tw.GetMethods()) + { + if (!mw.IsHideFromReflection && (mw.IsPublic || mw.IsProtected || includeNonPublicMembers)) + { + IKVM.StubGen.FieldOrMethod m; + if (mw.Name == "<init>") + { + m = writer.AddMethod(mw.Modifiers, mw.Name, mw.Signature.Replace('.', '/')); + IKVM.StubGen.CodeAttribute code = new IKVM.StubGen.CodeAttribute(writer); + code.MaxLocals = (ushort)(mw.GetParameters().Length * 2 + 1); + code.MaxStack = 3; + ushort index1 = writer.AddClass("java/lang/UnsatisfiedLinkError"); + ushort index2 = writer.AddString("ikvmstub generated stubs can only be used on IKVM.NET"); + ushort index3 = writer.AddMethodRef("java/lang/UnsatisfiedLinkError", "<init>", "(Ljava/lang/String;)V"); + code.ByteCode = new byte[] { + 187, (byte)(index1 >> 8), (byte)index1, // new java/lang/UnsatisfiedLinkError + 89, // dup + 19, (byte)(index2 >> 8), (byte)index2, // ldc_w "..." + 183, (byte)(index3 >> 8), (byte)index3, // invokespecial java/lang/UnsatisfiedLinkError/init()V + 191 // athrow + }; + m.AddAttribute(code); + } + else + { + Modifiers mods = mw.Modifiers; + if ((mods & Modifiers.Abstract) == 0) + { + mods |= Modifiers.Native; + } + m = writer.AddMethod(mods, mw.Name, mw.Signature.Replace('.', '/')); + if (mw.IsOptionalAttributeAnnotationValue) + { + m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, mw.ReturnType))); + } + } + MethodBase mb = mw.GetMethod(); + if (mb != null) + { + ThrowsAttribute throws = AttributeHelper.GetThrows(mb); + if (throws == null) + { + string[] throwsArray = mw.GetDeclaredExceptions(); + if (throwsArray != null && throwsArray.Length > 0) + { + IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer); + foreach (string ex in throwsArray) + { + attrib.Add(ex.Replace('.', '/')); + } + m.AddAttribute(attrib); + } + } + else + { + IKVM.StubGen.ExceptionsAttribute attrib = new IKVM.StubGen.ExceptionsAttribute(writer); + if (throws.classes != null) + { + foreach (string ex in throws.classes) + { + attrib.Add(ex.Replace('.', '/')); + } + } + if (throws.types != null) + { + foreach (Type ex in throws.types) + { + attrib.Add(ClassLoaderWrapper.GetWrapperFromType(ex).Name.Replace('.', '/')); + } + } + m.AddAttribute(attrib); + } + if (mb.IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false) + // HACK the instancehelper methods are marked as Obsolete (to direct people toward the ikvm.extensions methods instead) + // but in the Java world most of them are not deprecated (and to keep the Japi results clean we need to reflect this) + && (!mb.Name.StartsWith("instancehelper_") + || mb.DeclaringType.FullName != "java.lang.String" + // the Java deprecated methods actually have two Obsolete attributes + || GetObsoleteCount(mb) == 2)) + { + m.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); + } + CustomAttributeData attr = GetAnnotationDefault(mb); + if (attr != null) + { + m.AddAttribute(new IKVM.StubGen.AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, attr.ConstructorArguments[0]))); + } + } + string sig = tw.GetGenericMethodSignature(mw); + if (sig != null) + { + m.AddAttribute(writer.MakeStringAttribute("Signature", sig)); + } + } + } + bool hasSerialVersionUID = false; + foreach (FieldWrapper fw in tw.GetFields()) + { + if (!fw.IsHideFromReflection) + { + bool isSerialVersionUID = includeSerialVersionUID && fw.Name == "serialVersionUID" && fw.FieldTypeWrapper == PrimitiveTypeWrapper.LONG; + hasSerialVersionUID |= isSerialVersionUID; + if (fw.IsPublic || fw.IsProtected || isSerialVersionUID || includeNonPublicMembers) + { + object constant = null; + if (fw.GetField() != null && fw.GetField().IsLiteral && (fw.FieldTypeWrapper.IsPrimitive || fw.FieldTypeWrapper == CoreClasses.java.lang.String.Wrapper)) + { + constant = fw.GetField().GetRawConstantValue(); + if (fw.GetField().FieldType.IsEnum) + { + constant = EnumHelper.GetPrimitiveValue(EnumHelper.GetUnderlyingType(fw.GetField().FieldType), constant); + } + } + IKVM.StubGen.FieldOrMethod f = writer.AddField(fw.Modifiers, fw.Name, fw.Signature.Replace('.', '/'), constant); + string sig = tw.GetGenericFieldSignature(fw); + if (sig != null) + { + f.AddAttribute(writer.MakeStringAttribute("Signature", sig)); + } + if (fw.GetField() != null && fw.GetField().IsDefined(JVM.Import(typeof(ObsoleteAttribute)), false)) + { + f.AddAttribute(new IKVM.StubGen.DeprecatedAttribute(writer)); + } + } + } + } + if (includeSerialVersionUID && !hasSerialVersionUID && IsSerializable(tw)) + { + // class is serializable but doesn't have an explicit serialVersionUID, so we add the field to record + // the serialVersionUID as we see it (mainly to make the Japi reports more realistic) + writer.AddField(Modifiers.Private | Modifiers.Static | Modifiers.Final, "serialVersionUID", "J", IKVM.StubGen.SerialVersionUID.Compute(tw)); + } + AddMetaAnnotations(writer, tw); + writer.Write(stream); + } + + private static int GetObsoleteCount(MethodBase mb) + { +#if STUB_GENERATOR + return mb.__GetCustomAttributes(JVM.Import(typeof(ObsoleteAttribute)), false).Count; +#else + return mb.GetCustomAttributes(typeof(ObsoleteAttribute), false).Length; +#endif + } + + private static CustomAttributeData GetAnnotationDefault(MethodBase mb) + { +#if STUB_GENERATOR + IList<CustomAttributeData> attr = CustomAttributeData.__GetCustomAttributes(mb, JVM.LoadType(typeof(AnnotationDefaultAttribute)), false); + return attr.Count == 1 ? attr[0] : null; +#else + foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mb)) + { + if (cad.Constructor.DeclaringType == typeof(AnnotationDefaultAttribute)) + { + return cad; + } + } + return null; +#endif + } + + private static string GetAssemblyName(TypeWrapper tw) + { + ClassLoaderWrapper loader = tw.GetClassLoader(); + AssemblyClassLoader acl = loader as AssemblyClassLoader; + if (acl != null) + { + return acl.GetAssembly(tw).FullName; + } + else + { + return ((GenericClassLoaderWrapper)loader).GetName(); + } + } + + private static bool IsSerializable(TypeWrapper tw) + { + if (tw.Name == "java.io.Serializable") + { + return true; + } + while (tw != null) + { + foreach (TypeWrapper iface in tw.Interfaces) + { + if (IsSerializable(iface)) + { + return true; + } + } + tw = tw.BaseTypeWrapper; + } + return false; + } + + private static void AddMetaAnnotations(IKVM.StubGen.ClassFileWriter writer, TypeWrapper tw) + { + DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase attributeAnnotation = tw as DotNetTypeWrapper.AttributeAnnotationTypeWrapperBase; + if (attributeAnnotation != null) + { + // TODO write the annotation directly, instead of going thru the object[] encoding + IKVM.StubGen.RuntimeVisibleAnnotationsAttribute annot = new IKVM.StubGen.RuntimeVisibleAnnotationsAttribute(writer); + annot.Add(new object[] { + AnnotationDefaultAttribute.TAG_ANNOTATION, + "Ljava/lang/annotation/Retention;", + "value", + new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME" } + }); + AttributeTargets validOn = attributeAnnotation.AttributeTargets; + List<object[]> targets = new List<object[]>(); + if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0) + { + targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "TYPE" }); + } + if ((validOn & AttributeTargets.Constructor) != 0) + { + targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "CONSTRUCTOR" }); + } + if ((validOn & AttributeTargets.Field) != 0) + { + targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "FIELD" }); + } + if ((validOn & (AttributeTargets.Method | AttributeTargets.ReturnValue)) != 0) + { + targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "METHOD" }); + } + if ((validOn & AttributeTargets.Parameter) != 0) + { + targets.Add(new object[] { AnnotationDefaultAttribute.TAG_ENUM, "Ljava/lang/annotation/ElementType;", "PARAMETER" }); + } + annot.Add(new object[] { + AnnotationDefaultAttribute.TAG_ANNOTATION, + "Ljava/lang/annotation/Target;", + "value", + new object[] { AnnotationDefaultAttribute.TAG_ARRAY, targets.ToArray() } + }); + writer.AddAttribute(annot); + } + } + + private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, TypeWrapper type) + { + MemoryStream mem = new MemoryStream(); + IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem); + if (type == PrimitiveTypeWrapper.BOOLEAN) + { + bes.WriteByte((byte)'Z'); + bes.WriteUInt16(classFile.AddInt(0)); + } + else if (type == PrimitiveTypeWrapper.BYTE) + { + bes.WriteByte((byte)'B'); + bes.WriteUInt16(classFile.AddInt(0)); + } + else if (type == PrimitiveTypeWrapper.CHAR) + { + bes.WriteByte((byte)'C'); + bes.WriteUInt16(classFile.AddInt(0)); + } + else if (type == PrimitiveTypeWrapper.SHORT) + { + bes.WriteByte((byte)'S'); + bes.WriteUInt16(classFile.AddInt(0)); + } + else if (type == PrimitiveTypeWrapper.INT) + { + bes.WriteByte((byte)'I'); + bes.WriteUInt16(classFile.AddInt(0)); + } + else if (type == PrimitiveTypeWrapper.FLOAT) + { + bes.WriteByte((byte)'F'); + bes.WriteUInt16(classFile.AddFloat(0)); + } + else if (type == PrimitiveTypeWrapper.LONG) + { + bes.WriteByte((byte)'J'); + bes.WriteUInt16(classFile.AddLong(0)); + } + else if (type == PrimitiveTypeWrapper.DOUBLE) + { + bes.WriteByte((byte)'D'); + bes.WriteUInt16(classFile.AddDouble(0)); + } + else if (type == CoreClasses.java.lang.String.Wrapper) + { + bes.WriteByte((byte)'s'); + bes.WriteUInt16(classFile.AddUtf8("")); + } + else if ((type.Modifiers & Modifiers.Enum) != 0) + { + bes.WriteByte((byte)'e'); + bes.WriteUInt16(classFile.AddUtf8("L" + type.Name.Replace('.', '/') + ";")); + bes.WriteUInt16(classFile.AddUtf8("__unspecified")); + } + else if (type == CoreClasses.java.lang.Class.Wrapper) + { + bes.WriteByte((byte)'c'); + bes.WriteUInt16(classFile.AddUtf8("Likvm/internal/__unspecified;")); + } + else if (type.IsArray) + { + bes.WriteByte((byte)'['); + bes.WriteUInt16(0); + } + else + { + throw new InvalidOperationException(); + } + return mem.ToArray(); + } + + private static byte[] GetAnnotationDefault(IKVM.StubGen.ClassFileWriter classFile, CustomAttributeTypedArgument value) + { + MemoryStream mem = new MemoryStream(); + IKVM.StubGen.BigEndianStream bes = new IKVM.StubGen.BigEndianStream(mem); + try + { + WriteAnnotationElementValue(classFile, bes, value); + } + catch (InvalidCastException) + { + Console.Error.WriteLine("Warning: incorrect annotation default value"); + } + catch (IndexOutOfRangeException) + { + Console.Error.WriteLine("Warning: incorrect annotation default value"); + } + return mem.ToArray(); + } + + private static void WriteAnnotationElementValue(IKVM.StubGen.ClassFileWriter classFile, IKVM.StubGen.BigEndianStream bes, CustomAttributeTypedArgument value) + { + if (value.ArgumentType == Types.Boolean) + { + bes.WriteByte((byte)'Z'); + bes.WriteUInt16(classFile.AddInt((bool)value.Value ? 1 : 0)); + } + else if (value.ArgumentType == Types.Byte) + { + bes.WriteByte((byte)'B'); + bes.WriteUInt16(classFile.AddInt((byte)value.Value)); + } + else if (value.ArgumentType == Types.Char) + { + bes.WriteByte((byte)'C'); + bes.WriteUInt16(classFile.AddInt((char)value.Value)); + } + else if (value.ArgumentType == Types.Int16) + { + bes.WriteByte((byte)'S'); + bes.WriteUInt16(classFile.AddInt((short)value.Value)); + } + else if (value.ArgumentType == Types.Int32) + { + bes.WriteByte((byte)'I'); + bes.WriteUInt16(classFile.AddInt((int)value.Value)); + } + else if (value.ArgumentType == Types.Single) + { + bes.WriteByte((byte)'F'); + bes.WriteUInt16(classFile.AddFloat((float)value.Value)); + } + else if (value.ArgumentType == Types.Int64) + { + bes.WriteByte((byte)'J'); + bes.WriteUInt16(classFile.AddLong((long)value.Value)); + } + else if (value.ArgumentType == Types.Double) + { + bes.WriteByte((byte)'D'); + bes.WriteUInt16(classFile.AddDouble((double)value.Value)); + } + else if (value.ArgumentType == Types.String) + { + bes.WriteByte((byte)'s'); + bes.WriteUInt16(classFile.AddUtf8((string)value.Value)); + } + else if (value.ArgumentType == Types.Object.MakeArrayType()) + { + CustomAttributeTypedArgument[] array = (CustomAttributeTypedArgument[])value.Value; + byte type = (byte)array[0].Value; + if (type == AnnotationDefaultAttribute.TAG_ARRAY) + { + bes.WriteByte((byte)'['); + bes.WriteUInt16((ushort)(array.Length - 1)); + for (int i = 1; i < array.Length; i++) + { + WriteAnnotationElementValue(classFile, bes, array[i]); + } + } + else if (type == AnnotationDefaultAttribute.TAG_CLASS) + { + bes.WriteByte((byte)'c'); + bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); + } + else if (type == AnnotationDefaultAttribute.TAG_ENUM) + { + bes.WriteByte((byte)'e'); + bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); + bes.WriteUInt16(classFile.AddUtf8((string)array[2].Value)); + } + else if (type == AnnotationDefaultAttribute.TAG_ANNOTATION) + { + bes.WriteByte((byte)'@'); + bes.WriteUInt16(classFile.AddUtf8((string)array[1].Value)); + bes.WriteUInt16((ushort)((array.Length - 2) / 2)); + for (int i = 2; i < array.Length; i += 2) + { + bes.WriteUInt16(classFile.AddUtf8((string)array[i].Value)); + WriteAnnotationElementValue(classFile, bes, array[i + 1]); + } + } + else + { + Console.Error.WriteLine("Warning: incorrect annotation default element tag: " + type); + } + } + else + { + Console.Error.WriteLine("Warning: incorrect annotation default element type: " + value.ArgumentType); + } + } + } +} diff --git a/runtime/vfs.cs b/runtime/vfs.cs index 04944b37..8db1165e 100644 --- a/runtime/vfs.cs +++ b/runtime/vfs.cs @@ -575,7 +575,10 @@ namespace IKVM.Internal #if !FIRST_PASS if (buf == null) { - buf = ikvm.@internal.stubgen.StubGenerator.generateStub(tw.ClassObject); + System.IO.MemoryStream mem = new System.IO.MemoryStream(); + bool includeNonPublicInterfaces = !"true".Equals(java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase); + IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, false, false); + buf = mem.ToArray(); } #endif } |