diff --git a/classpath/avian/Classes.java b/classpath/avian/Classes.java index e5c3d9fa69..a50118e1b3 100644 --- a/classpath/avian/Classes.java +++ b/classpath/avian/Classes.java @@ -317,7 +317,7 @@ public class Classes { int index = 0; String spec = new String - (vmMethod.spec, 1, vmMethod.spec.length - 1); + (vmMethod.spec, 1, vmMethod.spec.length - 2); try { for (int i = 0; i < spec.length(); ++i) { @@ -353,6 +353,7 @@ public class Classes { return types; } + public static int findField(VMClass vmClass, String name) { if (vmClass.fieldTable != null) { Classes.link(vmClass); @@ -370,7 +371,7 @@ public class Classes { return new String(array, 0, array.length - 1); } - private static boolean match(Class[] a, Class[] b) { + public static boolean match(Class[] a, Class[] b) { if (a.length == b.length) { for (int i = 0; i < a.length; ++i) { if (! a[i].isAssignableFrom(b[i])) { @@ -383,7 +384,7 @@ public class Classes { } } - private static int findMethod(VMClass vmClass, String name, + public static int findMethod(VMClass vmClass, String name, Class[] parameterTypes) { if (vmClass.methodTable != null) { diff --git a/classpath/java/lang/Boolean.java b/classpath/java/lang/Boolean.java index ddd3bec725..be8b57ddcb 100644 --- a/classpath/java/lang/Boolean.java +++ b/classpath/java/lang/Boolean.java @@ -11,7 +11,7 @@ package java.lang; public final class Boolean implements Comparable { - public static final Class TYPE = Class.forCanonicalName("Z"); + public static final Class TYPE = avian.Classes.forCanonicalName("Z"); public static final Boolean FALSE = new Boolean(false); public static final Boolean TRUE = new Boolean(true); diff --git a/classpath/java/lang/Byte.java b/classpath/java/lang/Byte.java index 1133d6ec03..460ff0a51f 100644 --- a/classpath/java/lang/Byte.java +++ b/classpath/java/lang/Byte.java @@ -11,7 +11,7 @@ package java.lang; public final class Byte extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("B"); + public static final Class TYPE = avian.Classes.forCanonicalName("B"); private final byte value; diff --git a/classpath/java/lang/Character.java b/classpath/java/lang/Character.java index 3e7f1ed269..1cbeb1cea7 100644 --- a/classpath/java/lang/Character.java +++ b/classpath/java/lang/Character.java @@ -14,7 +14,7 @@ public final class Character implements Comparable { public static final int MIN_RADIX = 2; public static final int MAX_RADIX = 36; - public static final Class TYPE = Class.forCanonicalName("C"); + public static final Class TYPE = avian.Classes.forCanonicalName("C"); private final char value; diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index a37fb96e59..baebcae4c9 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -191,7 +191,7 @@ public final class Class implements Type, AnnotatedElement { public Field getField(String name) throws NoSuchFieldException { for (VMClass c = vmClass; c != null; c = c.super_) { - int index = findField(c, name); + int index = Classes.findField(c, name); if (index >= 0) { return new Field(vmClass.fieldTable[index]); } @@ -220,7 +220,7 @@ public final class Class implements Type, AnnotatedElement { throw new NoSuchMethodException(name); } for (VMClass c = vmClass; c != null; c = c.super_) { - int index = findMethod(c, name, parameterTypes); + int index = Classes.findMethod(c, name, parameterTypes); if (index >= 0) { return new Method(vmClass.methodTable[index]); } @@ -231,11 +231,11 @@ public final class Class implements Type, AnnotatedElement { public Constructor getConstructor(Class ... parameterTypes) throws NoSuchMethodException { - Method m = findMethod(vmClass, "", parameterTypes); - if (m == null) { + int index = Classes.findMethod(vmClass, "", parameterTypes); + if (index < 0) { throw new NoSuchMethodException(); } else { - return new Constructor(m); + return new Constructor(new Method(vmClass.methodTable[index])); } } @@ -246,7 +246,7 @@ public final class Class implements Type, AnnotatedElement { Constructor[] constructors = getDeclaredConstructors(); for (int i = 0; i < constructors.length; ++i) { - if (match(parameterTypes, constructors[i].getParameterTypes())) { + if (Classes.match(parameterTypes, constructors[i].getParameterTypes())) { c = constructors[i]; } } diff --git a/classpath/java/lang/Double.java b/classpath/java/lang/Double.java index a58f9fcb39..8d145ce4d9 100644 --- a/classpath/java/lang/Double.java +++ b/classpath/java/lang/Double.java @@ -11,7 +11,7 @@ package java.lang; public final class Double extends Number { - public static final Class TYPE = Class.forCanonicalName("D"); + public static final Class TYPE = avian.Classes.forCanonicalName("D"); public static final double NEGATIVE_INFINITY = -1.0 / 0.0; public static final double POSITIVE_INFINITY = 1.0 / 0.0; diff --git a/classpath/java/lang/Float.java b/classpath/java/lang/Float.java index f04e728bac..652659f307 100644 --- a/classpath/java/lang/Float.java +++ b/classpath/java/lang/Float.java @@ -11,7 +11,7 @@ package java.lang; public final class Float extends Number { - public static final Class TYPE = Class.forCanonicalName("F"); + public static final Class TYPE = avian.Classes.forCanonicalName("F"); private static final int EXP_BIT_MASK = 0x7F800000; private static final int SIGNIF_BIT_MASK = 0x007FFFFF; diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 9bd399f227..f5e4052904 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -11,7 +11,7 @@ package java.lang; public final class Integer extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("I"); + public static final Class TYPE = avian.Classes.forCanonicalName("I"); public static final int MIN_VALUE = 0x80000000; public static final int MAX_VALUE = 0x7FFFFFFF; diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index 425e68383a..3023ad03de 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -14,7 +14,7 @@ public final class Long extends Number implements Comparable { public static final long MIN_VALUE = -9223372036854775808l; public static final long MAX_VALUE = 9223372036854775807l; - public static final Class TYPE = Class.forCanonicalName("J"); + public static final Class TYPE = avian.Classes.forCanonicalName("J"); private final long value; diff --git a/classpath/java/lang/Short.java b/classpath/java/lang/Short.java index f218bb8cec..2158c8ebec 100644 --- a/classpath/java/lang/Short.java +++ b/classpath/java/lang/Short.java @@ -11,7 +11,7 @@ package java.lang; public final class Short extends Number implements Comparable { - public static final Class TYPE = Class.forCanonicalName("S"); + public static final Class TYPE = avian.Classes.forCanonicalName("S"); public static final short MAX_VALUE = 32767; private final short value; diff --git a/classpath/java/lang/String.java b/classpath/java/lang/String.java index 24a893ad87..ff91fdbc78 100644 --- a/classpath/java/lang/String.java +++ b/classpath/java/lang/String.java @@ -127,6 +127,11 @@ public final class String } else { c = Utf8.decode((byte[])data, offset, length); if(c instanceof char[]) length = ((char[])c).length; + if (c == null) { + throw new RuntimeException + ("unable to parse \"" + new String(data, offset, length, false) + + "\""); + } } this.data = c; diff --git a/classpath/java/lang/Void.java b/classpath/java/lang/Void.java index 89137eea57..55e28e2abf 100644 --- a/classpath/java/lang/Void.java +++ b/classpath/java/lang/Void.java @@ -11,7 +11,7 @@ package java.lang; public final class Void { - public static final Class TYPE = Class.forCanonicalName("V"); + public static final Class TYPE = avian.Classes.forCanonicalName("V"); private Void() { } } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 8d76a6258f..f366341534 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -61,7 +61,7 @@ public class Field extends AccessibleObject { } public Class getType() { - return Class.forCanonicalName + return Classes.forCanonicalName (vmField.class_.loader, new String(vmField.spec, 0, vmField.spec.length - 1, false)); } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index a572f3eb49..f06edf4c03 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -13,6 +13,7 @@ package java.lang.reflect; import avian.VMMethod; import avian.AnnotationInvocationHandler; import avian.SystemClassLoader; +import avian.Classes; import java.lang.annotation.Annotation; @@ -98,7 +99,7 @@ public class Method extends AccessibleObject implements Member { public Class getReturnType() { for (int i = 0; i < vmMethod.spec.length - 1; ++i) { if (vmMethod.spec[i] == ')') { - return Class.forCanonicalName + return Classes.forCanonicalName (vmMethod.class_.loader, new String (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false)); diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 58ab70e792..7e637c2581 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -127,6 +127,47 @@ class MyClasspath : public Classpath { // ignore } + virtual object + makeDirectByteBuffer(Thread* t, void* p, jlong capacity) + { + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/nio/DirectByteBuffer"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(JI)V"); + + t->m->processor->invoke + (t, constructor, instance, reinterpret_cast(p), + static_cast(capacity)); + + return instance; + } + + virtual void* + getDirectBufferAddress(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField(t, objectClass(t, b), "address", "J"); + + return reinterpret_cast + (fieldAtOffset(b, fieldOffset(t, field))); + } + + virtual int64_t + getDirectBufferCapacity(Thread* t, object b) + { + PROTECT(t, b); + + object field = resolveField + (t, objectClass(t, b), "capacity", "I"); + + return fieldAtOffset(b, fieldOffset(t, field)); + } + virtual void dispose() { @@ -698,3 +739,41 @@ Avian_avian_Classes_getVMClass return reinterpret_cast (objectClass(t, reinterpret_cast(arguments[0]))); } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_Classes_makeMethod +(Thread* t, object, uintptr_t* arguments) +{ + object method = arrayBody + (t, classMethodTable + (t, jclassVmClass(t, reinterpret_cast(arguments[0]))), + arguments[1]); + PROTECT(t, method); + + object c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/reflect/Method"); + PROTECT(t, c); + + object instance = makeNew(t, c); + PROTECT(t, instance); + + object constructor = resolveMethod(t, c, "", "(Lavian/VMMethod;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + + if (byteArrayBody(t, methodName(t, method), 0) == '<') { + method = instance; + + c = resolveClass + (t, root(t, Machine::BootLoader), "java/lang/reflect/Constructor"); + + object instance = makeNew(t, c); + + object constructor = resolveMethod + (t, c, "", "(Ljava/lang/Method;)V"); + + t->m->processor->invoke(t, constructor, instance, method); + } + + return reinterpret_cast(instance); +}