Changed JNI reflection to be based on Java reflection (where possible).

This commit is contained in:
jfrijters 2008-08-21 06:40:22 +00:00
Родитель 316dd359eb
Коммит 6bce58f1bc
5 изменённых файлов: 202 добавлений и 74 удалений

Просмотреть файл

@ -1405,7 +1405,8 @@ namespace IKVM.Runtime
try try
{ {
wrapper.Finish(); wrapper.Finish();
exception = (Exception)mw.InvokeJNI(null, new object[] { StringFromOEM(msg) }, false, null); java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)mw.ToMethodOrConstructor(false);
exception = (Exception)cons.newInstance(new object[] { StringFromOEM(msg) }, (ikvm.@internal.CallerID)JVM.CreateCallerID(pEnv->currentMethod));
rc = JNI_OK; rc = JNI_OK;
} }
catch(RetargetableJavaException x) catch(RetargetableJavaException x)
@ -1635,28 +1636,28 @@ namespace IKVM.Runtime
switch(sig[i]) switch(sig[i])
{ {
case 'Z': case 'Z':
argarray[i] = args[i].z != JNI_FALSE; argarray[i] = java.lang.Boolean.valueOf(args[i].z != JNI_FALSE);
break; break;
case 'B': case 'B':
argarray[i] = args[i].b; argarray[i] = java.lang.Byte.valueOf((byte)args[i].b);
break; break;
case 'C': case 'C':
argarray[i] = (char)args[i].c; argarray[i] = java.lang.Character.valueOf((char)args[i].c);
break; break;
case 'S': case 'S':
argarray[i] = args[i].s; argarray[i] = java.lang.Short.valueOf(args[i].s);
break; break;
case 'I': case 'I':
argarray[i] = args[i].i; argarray[i] = java.lang.Integer.valueOf(args[i].i);
break; break;
case 'J': case 'J':
argarray[i] = args[i].j; argarray[i] = java.lang.Long.valueOf(args[i].j);
break; break;
case 'F': case 'F':
argarray[i] = args[i].f; argarray[i] = java.lang.Float.valueOf(args[i].f);
break; break;
case 'D': case 'D':
argarray[i] = args[i].d; argarray[i] = java.lang.Double.valueOf(args[i].d);
break; break;
case 'L': case 'L':
argarray[i] = pEnv->UnwrapRef(args[i].l); argarray[i] = pEnv->UnwrapRef(args[i].l);
@ -2003,120 +2004,99 @@ namespace IKVM.Runtime
return FindFieldID(pEnv, clazz, name, sig, false); return FindFieldID(pEnv, clazz, name, sig, false);
} }
private static void SetFieldValue(jfieldID cookie, object obj, object val) private static sun.reflect.FieldAccessor GetFieldAccessor(jfieldID cookie)
{ {
try return (sun.reflect.FieldAccessor)FieldWrapper.FromCookie(cookie).GetFieldAccessorJNI();
{
FieldWrapper.FromCookie(cookie).SetValue(obj, val);
}
catch
{
Debug.Assert(false);
throw;
}
}
private static object GetFieldValue(jfieldID cookie, object obj)
{
try
{
return FieldWrapper.FromCookie(cookie).GetValue(obj);
}
catch
{
Debug.Assert(false);
throw;
}
} }
internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return pEnv->MakeLocalRef(GetFieldValue(fieldID, pEnv->UnwrapRef(obj))); return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(pEnv->UnwrapRef(obj)));
} }
internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return ((bool)GetFieldValue(fieldID, pEnv->UnwrapRef(obj))) ? JNI_TRUE : JNI_FALSE; return GetFieldAccessor(fieldID).getBoolean(pEnv->UnwrapRef(obj)) ? JNI_TRUE : JNI_FALSE;
} }
internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jbyte)(byte)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jbyte)GetFieldAccessor(fieldID).getByte(pEnv->UnwrapRef(obj));
} }
internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jchar)(char)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jchar)GetFieldAccessor(fieldID).getChar(pEnv->UnwrapRef(obj));
} }
internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jshort)(short)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jshort)GetFieldAccessor(fieldID).getShort(pEnv->UnwrapRef(obj));
} }
internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jint)(int)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jint)GetFieldAccessor(fieldID).getInt(pEnv->UnwrapRef(obj));
} }
internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jlong)(long)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jlong)GetFieldAccessor(fieldID).getLong(pEnv->UnwrapRef(obj));
} }
internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jfloat)(float)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jfloat)GetFieldAccessor(fieldID).getFloat(pEnv->UnwrapRef(obj));
} }
internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jdouble)(double)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jdouble)GetFieldAccessor(fieldID).getDouble(pEnv->UnwrapRef(obj));
} }
internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val) internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val)); GetFieldAccessor(fieldID).set(pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val));
} }
internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val) internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val != JNI_FALSE); GetFieldAccessor(fieldID).setBoolean(pEnv->UnwrapRef(obj), val != JNI_FALSE);
} }
internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val) internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (byte)val); GetFieldAccessor(fieldID).setByte(pEnv->UnwrapRef(obj), (byte)val);
} }
internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val) internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (char)val); GetFieldAccessor(fieldID).setChar(pEnv->UnwrapRef(obj), (char)val);
} }
internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val) internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (short)val); GetFieldAccessor(fieldID).setShort(pEnv->UnwrapRef(obj), (short)val);
} }
internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val) internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (int)val); GetFieldAccessor(fieldID).setInt(pEnv->UnwrapRef(obj), (int)val);
} }
internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val) internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (long)val); GetFieldAccessor(fieldID).setLong(pEnv->UnwrapRef(obj), (long)val);
} }
internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val) internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (float)val); GetFieldAccessor(fieldID).setFloat(pEnv->UnwrapRef(obj), (float)val);
} }
internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val) internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (double)val); GetFieldAccessor(fieldID).setDouble(pEnv->UnwrapRef(obj), (double)val);
} }
internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig) internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
@ -2221,92 +2201,92 @@ namespace IKVM.Runtime
internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return pEnv->MakeLocalRef(GetFieldValue(fieldID, null)); return pEnv->MakeLocalRef(GetFieldAccessor(fieldID).get(null));
} }
internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return ((bool)GetFieldValue(fieldID, null)) ? JNI_TRUE : JNI_FALSE; return GetFieldAccessor(fieldID).getBoolean(null) ? JNI_TRUE : JNI_FALSE;
} }
internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jbyte)(byte)GetFieldValue(fieldID, null); return (jbyte)GetFieldAccessor(fieldID).getByte(null);
} }
internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jchar)(char)GetFieldValue(fieldID, null); return (jchar)GetFieldAccessor(fieldID).getChar(null);
} }
internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jshort)(short)GetFieldValue(fieldID, null); return (jshort)GetFieldAccessor(fieldID).getShort(null);
} }
internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jint)(int)GetFieldValue(fieldID, null); return (jint)GetFieldAccessor(fieldID).getInt(null);
} }
internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jlong)(long)GetFieldValue(fieldID, null); return (jlong)GetFieldAccessor(fieldID).getLong(null);
} }
internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jfloat)(float)GetFieldValue(fieldID, null); return (jfloat)GetFieldAccessor(fieldID).getFloat(null);
} }
internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jdouble)(double)GetFieldValue(fieldID, null); return (jdouble)GetFieldAccessor(fieldID).getDouble(null);
} }
internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val) internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val)
{ {
SetFieldValue(fieldID, null, pEnv->UnwrapRef(val)); GetFieldAccessor(fieldID).set(null, pEnv->UnwrapRef(val));
} }
internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val) internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val)
{ {
SetFieldValue(fieldID, null, val != JNI_FALSE); GetFieldAccessor(fieldID).setBoolean(null, val != JNI_FALSE);
} }
internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val) internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val)
{ {
SetFieldValue(fieldID, null, (byte)val); GetFieldAccessor(fieldID).setByte(null, (byte)val);
} }
internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val) internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val)
{ {
SetFieldValue(fieldID, null, (char)val); GetFieldAccessor(fieldID).setChar(null, (char)val);
} }
internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val) internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val)
{ {
SetFieldValue(fieldID, null, (short)val); GetFieldAccessor(fieldID).setShort(null, (short)val);
} }
internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val) internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val)
{ {
SetFieldValue(fieldID, null, (int)val); GetFieldAccessor(fieldID).setInt(null, (int)val);
} }
internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val) internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val)
{ {
SetFieldValue(fieldID, null, (long)val); GetFieldAccessor(fieldID).setLong(null, (long)val);
} }
internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val) internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val)
{ {
SetFieldValue(fieldID, null, (float)val); GetFieldAccessor(fieldID).setFloat(null, (float)val);
} }
internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val) internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val)
{ {
SetFieldValue(fieldID, null, (double)val); GetFieldAccessor(fieldID).setDouble(null, (double)val);
} }
internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len) internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len)

Просмотреть файл

@ -29,6 +29,7 @@ using System.Reflection.Emit;
#endif #endif
using System.Diagnostics; using System.Diagnostics;
using IKVM.Attributes; using IKVM.Attributes;
using System.Threading;
namespace IKVM.Internal namespace IKVM.Internal
{ {
@ -278,6 +279,7 @@ namespace IKVM.Internal
abstract class MethodWrapper : MemberWrapper abstract class MethodWrapper : MemberWrapper
{ {
#if !STATIC_COMPILER && !FIRST_PASS #if !STATIC_COMPILER && !FIRST_PASS
private static Dictionary<MethodWrapper, sun.reflect.MethodAccessor> invokenonvirtualCache;
private volatile object reflectionMethod; private volatile object reflectionMethod;
#endif #endif
internal static readonly MethodWrapper[] EmptyArray = new MethodWrapper[0]; internal static readonly MethodWrapper[] EmptyArray = new MethodWrapper[0];
@ -704,9 +706,122 @@ namespace IKVM.Internal
#if FIRST_PASS #if FIRST_PASS
return null; return null;
#else #else
return Invoke(obj, args, nonVirtual, ikvm.@internal.CallerID.create(callerID)); if (ReferenceEquals(Name, StringConstants.INIT))
{
java.lang.reflect.Constructor cons = (java.lang.reflect.Constructor)ToMethodOrConstructor(false);
if (obj == null)
{
sun.reflect.ConstructorAccessor acc = cons.getConstructorAccessor();
if (acc == null)
{
acc = reflectionFactory.newConstructorAccessor(cons);
cons.setConstructorAccessor(acc);
}
return acc.newInstance(args);
}
else if (method is MethodInfo)
{
Debug.Assert(method.IsStatic);
// we're dealing with a constructor on a remapped type, if obj is supplied, it means
// that we should call the constructor on an already existing instance, but that isn't
// possible with remapped types
// the type of this exception is a bit random (note that this can only happen through JNI reflection)
throw new java.lang.IncompatibleClassChangeError(string.Format("Remapped type {0} doesn't support constructor invocation on an existing instance", DeclaringType.Name));
}
else if (!method.DeclaringType.IsInstanceOfType(obj))
{
// we're trying to initialize an existing instance of a remapped type
throw new NotSupportedException("Unable to partially construct object of type " + obj.GetType().FullName + " to type " + method.DeclaringType.FullName);
}
else
{
try
{
InvokeArgsProcessor proc = new InvokeArgsProcessor(this, method, obj, UnboxArgs(args), ikvm.@internal.CallerID.create(callerID));
object o = method.Invoke(proc.GetObj(), proc.GetArgs());
TypeWrapper retType = this.ReturnType;
if (!retType.IsUnloadable && retType.IsGhost)
{
o = retType.GhostRefField.GetValue(o);
}
return o;
}
catch (ArgumentException x1)
{
throw new java.lang.IllegalArgumentException(x1.Message);
}
catch (TargetInvocationException x)
{
throw new java.lang.reflect.InvocationTargetException(ikvm.runtime.Util.mapException(x.InnerException));
}
}
}
else if (nonVirtual
&& !this.IsStatic
&& !this.IsPrivate
&& !this.IsAbstract
&& !this.IsFinal
&& !this.DeclaringType.IsFinal)
{
if (this.DeclaringType.IsRemapped)
{
ResolveMethod();
return InvokeImpl(method, obj, UnboxArgs(args), true, ikvm.@internal.CallerID.create(callerID));
}
else
{
if (invokenonvirtualCache == null)
{
Interlocked.CompareExchange(ref invokenonvirtualCache, new Dictionary<MethodWrapper, sun.reflect.MethodAccessor>(), null);
}
sun.reflect.MethodAccessor acc;
lock (invokenonvirtualCache)
{
if (!invokenonvirtualCache.TryGetValue(this, out acc))
{
acc = new IKVM.NativeCode.sun.reflect.ReflectionFactory.FastMethodAccessorImpl((java.lang.reflect.Method)ToMethodOrConstructor(false), true);
invokenonvirtualCache.Add(this, acc);
}
}
object val = acc.invoke(obj, args, ikvm.@internal.CallerID.create(callerID));
if (this.ReturnType.IsPrimitive && this.ReturnType != PrimitiveTypeWrapper.VOID)
{
val = JVM.Unbox(val);
}
return val;
}
}
else
{
java.lang.reflect.Method method = (java.lang.reflect.Method)ToMethodOrConstructor(false);
sun.reflect.MethodAccessor acc = method.getMethodAccessor();
if (acc == null)
{
acc = reflectionFactory.newMethodAccessor(method);
method.setMethodAccessor(acc);
}
object val = acc.invoke(obj, args, ikvm.@internal.CallerID.create(callerID));
if (this.ReturnType.IsPrimitive && this.ReturnType != PrimitiveTypeWrapper.VOID)
{
val = JVM.Unbox(val);
}
return val;
}
#endif #endif
} }
private object[] UnboxArgs(object[] args)
{
TypeWrapper[] paramTypes = GetParameters();
for (int i = 0; i < paramTypes.Length; i++)
{
if (paramTypes[i].IsPrimitive)
{
args[i] = JVM.Unbox(args[i]);
}
}
return args;
}
#endif // !STATIC_COMPILER #endif // !STATIC_COMPILER
#if !STATIC_COMPILER && !FIRST_PASS #if !STATIC_COMPILER && !FIRST_PASS
@ -1183,6 +1298,7 @@ namespace IKVM.Internal
#if !STATIC_COMPILER && !FIRST_PASS #if !STATIC_COMPILER && !FIRST_PASS
private static readonly FieldInfo slotField = typeof(java.lang.reflect.Field).GetField("slot", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo slotField = typeof(java.lang.reflect.Field).GetField("slot", BindingFlags.Instance | BindingFlags.NonPublic);
private volatile object reflectionField; private volatile object reflectionField;
private sun.reflect.FieldAccessor jniAccessor;
#endif #endif
internal static readonly FieldWrapper[] EmptyArray = new FieldWrapper[0]; internal static readonly FieldWrapper[] EmptyArray = new FieldWrapper[0];
private FieldInfo field; private FieldInfo field;
@ -1414,6 +1530,19 @@ namespace IKVM.Internal
#endif #endif
} }
} }
internal object GetFieldAccessorJNI()
{
#if FIRST_PASS
return null;
#else
if (jniAccessor == null)
{
jniAccessor = reflectionFactory.newFieldAccessor((java.lang.reflect.Field)ToField(false), true);
}
return jniAccessor;
#endif
}
#endif // !STATIC_COMPILER #endif // !STATIC_COMPILER
internal virtual object GetValue(object obj) internal virtual object GetValue(object obj)

Просмотреть файл

@ -11315,7 +11315,13 @@ namespace IKVM.Internal
protected override void EmitSetImpl(CodeEmitter ilgen) protected override void EmitSetImpl(CodeEmitter ilgen)
{ {
throw new InvalidOperationException(); // NOTE even though the field is final, JNI reflection can still be used to set its value!
LocalBuilder temp = ilgen.AllocTempLocal(underlyingType);
ilgen.Emit(OpCodes.Stloc, temp);
ilgen.Emit(OpCodes.Unbox, underlyingType);
ilgen.Emit(OpCodes.Ldloc, temp);
ilgen.Emit(OpCodes.Stobj, underlyingType);
ilgen.ReleaseTempLocal(temp);
} }
#endif #endif

Просмотреть файл

@ -5859,7 +5859,7 @@ namespace IKVM.NativeCode.sun.reflect
} }
} }
private sealed class FastMethodAccessorImpl : srMethodAccessor internal sealed class FastMethodAccessorImpl : srMethodAccessor
{ {
private static readonly MethodInfo valueOfByte; private static readonly MethodInfo valueOfByte;
private static readonly MethodInfo valueOfBoolean; private static readonly MethodInfo valueOfBoolean;
@ -5927,7 +5927,7 @@ namespace IKVM.NativeCode.sun.reflect
} }
} }
internal FastMethodAccessorImpl(jlrMethod method) internal FastMethodAccessorImpl(jlrMethod method, bool nonvirtual)
{ {
MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(method); MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(method);
mw.DeclaringType.Finish(); mw.DeclaringType.Finish();
@ -6018,7 +6018,7 @@ namespace IKVM.NativeCode.sun.reflect
{ {
ilgen.Emit(OpCodes.Ldarg_2); ilgen.Emit(OpCodes.Ldarg_2);
} }
if (mw.IsStatic) if (mw.IsStatic || nonvirtual)
{ {
mw.EmitCall(ilgen); mw.EmitCall(ilgen);
} }
@ -7672,7 +7672,7 @@ namespace IKVM.NativeCode.sun.reflect
TypeWrapper tw = TypeWrapper.FromClass(m.getDeclaringClass()); TypeWrapper tw = TypeWrapper.FromClass(m.getDeclaringClass());
if (!mw.IsDynamicOnly && !tw.IsRemapped) if (!mw.IsDynamicOnly && !tw.IsRemapped)
{ {
return new FastMethodAccessorImpl(m); return new FastMethodAccessorImpl(m, false);
} }
} }
return new MethodAccessorImpl(m); return new MethodAccessorImpl(m);

Просмотреть файл

@ -379,6 +379,19 @@ namespace IKVM.Internal
} }
#endif #endif
#if !STATIC_COMPILER
// helper for JNI (which doesn't have access to core library internals)
internal static object CreateCallerID(RuntimeMethodHandle method)
{
#if FIRST_PASS
return null;
#else
return ikvm.@internal.CallerID.create(MethodBase.GetMethodFromHandle(method));
#endif
}
#endif
#if !STATIC_COMPILER #if !STATIC_COMPILER
// helper for JNI (which doesn't have access to core library internals) // helper for JNI (which doesn't have access to core library internals)
internal static object NewDirectByteBuffer(long address, int capacity) internal static object NewDirectByteBuffer(long address, int capacity)