diff options
author | jfrijters <jfrijters> | 2014-11-06 15:29:25 +0300 |
---|---|---|
committer | jfrijters <jfrijters> | 2014-11-06 15:29:25 +0300 |
commit | 7a47050861f1006cee45a1b6f3e07623247e0aa6 (patch) | |
tree | d0bcb22922edc726b1f4b1ba7acaa014f571808f | |
parent | 32448a0634a95e9380581e300be82faff56834d8 (diff) |
Made sun.misc.Unsafe array access more compatible with JDK. It is now possible to get/set primitive values from arrays of a different (primitive) type
-rw-r--r-- | openjdk/sun/misc/Unsafe.java | 286 | ||||
-rw-r--r-- | runtime/openjdk/sun.misc.cs | 512 |
2 files changed, 744 insertions, 54 deletions
diff --git a/openjdk/sun/misc/Unsafe.java b/openjdk/sun/misc/Unsafe.java index 748e3b02..1f8ae26a 100644 --- a/openjdk/sun/misc/Unsafe.java +++ b/openjdk/sun/misc/Unsafe.java @@ -1,5 +1,5 @@ /* - Copyright (C) 2006-2012 Jeroen Frijters + Copyright (C) 2006-2014 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 @@ -24,6 +24,7 @@ package sun.misc; +import cli.System.Buffer; import cli.System.IntPtr; import cli.System.Runtime.InteropServices.Marshal; import cli.System.Security.Permissions.SecurityAction; @@ -49,7 +50,7 @@ public final class Unsafe @sun.reflect.CallerSensitive public static Unsafe getUnsafe() { - if(ikvm.internal.CallerID.getCallerID().getCallerClassLoader() != null) + if(!VM.isSystemDomainLoader(ikvm.internal.CallerID.getCallerID().getCallerClassLoader())) { throw new SecurityException("Unsafe"); } @@ -59,7 +60,7 @@ public final class Unsafe // this is the intrinsified version of objectFieldOffset(XXX.class.getDeclaredField("xxx")) public long objectFieldOffset(Class c, String field) { - return fieldOffset(ReflectHelper.createFieldAndMakeAccessible(c, field)); + return allocateUnsafeFieldId(ReflectHelper.createFieldAndMakeAccessible(c, field)); } // NOTE we have a really lame (and slow) implementation! @@ -69,12 +70,17 @@ public final class Unsafe { throw new IllegalArgumentException(); } - return fieldOffset(field); + return allocateUnsafeFieldId(field); } @Deprecated public int fieldOffset(Field original) { + return allocateUnsafeFieldId(original); + } + + static int allocateUnsafeFieldId(Field original) + { Field copy = ReflectHelper.copyFieldAndMakeAccessible(original); synchronized(fields) { @@ -92,6 +98,22 @@ public final class Unsafe public int arrayIndexScale(Class c) { + if (c == byte[].class || c == boolean[].class) + { + return 1; + } + if (c == char[].class || c == short[].class) + { + return 2; + } + if (c == int[].class || c == float[].class) + { + return 4; + } + if (c == long[].class || c == double[].class) + { + return 8; + } // don't change this, the Unsafe intrinsics depend on this value return 1; } @@ -199,17 +221,22 @@ public final class Unsafe } } + private static native short ReadInt16(Object obj, long offset); + private static native int ReadInt32(Object obj, long offset); + private static native long ReadInt64(Object obj, long offset); + private static native void WriteInt16(Object obj, long offset, short value); + private static native void WriteInt32(Object obj, long offset, int value); + private static native void WriteInt64(Object obj, long offset, long value); + public boolean compareAndSwapInt(Object obj, long offset, int expect, int update) { - if(obj instanceof int[]) + if (obj instanceof cli.System.Array) { - int[] arr = (int[])obj; - int index = (int)offset; synchronized(this) { - if(arr[index] == expect) + if(ReadInt32(obj, offset) == expect) { - arr[index] = update; + WriteInt32(obj, offset, update); return true; } return false; @@ -239,11 +266,11 @@ public final class Unsafe public void putIntVolatile(Object obj, long offset, int newValue) { - if(obj instanceof int[]) + if (obj instanceof cli.System.Array) { synchronized(this) { - ((int[])obj)[(int)offset] = newValue; + WriteInt32(obj, offset, newValue); } } else @@ -270,11 +297,11 @@ public final class Unsafe public int getIntVolatile(Object obj, long offset) { - if(obj instanceof int[]) + if (obj instanceof cli.System.Array) { synchronized(this) { - return ((int[])obj)[(int)offset]; + return ReadInt32(obj, offset); } } else @@ -296,15 +323,13 @@ public final class Unsafe public boolean compareAndSwapLong(Object obj, long offset, long expect, long update) { - if(obj instanceof long[]) + if (obj instanceof cli.System.Array) { - long[] arr = (long[])obj; - int index = (int)offset; synchronized(this) { - if(arr[index] == expect) + if(ReadInt64(obj, offset) == expect) { - arr[index] = update; + WriteInt64(obj, offset, update); return true; } return false; @@ -334,11 +359,11 @@ public final class Unsafe public void putLongVolatile(Object obj, long offset, long newValue) { - if(obj instanceof long[]) + if (obj instanceof cli.System.Array) { synchronized(this) { - ((long[])obj)[(int)offset] = newValue; + WriteInt64(obj, offset, newValue); } } else @@ -365,11 +390,11 @@ public final class Unsafe public long getLongVolatile(Object obj, long offset) { - if(obj instanceof long[]) + if (obj instanceof cli.System.Array) { synchronized(this) { - return ((long[])obj)[(int)offset]; + return ReadInt64(obj, offset); } } else @@ -391,9 +416,9 @@ public final class Unsafe public void putBoolean(Object obj, long offset, boolean newValue) { - if (obj instanceof boolean[]) + if (obj instanceof cli.System.Array) { - ((boolean[])obj)[(int)offset] = newValue; + Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue ? (byte)1 : (byte)0); } else { @@ -408,11 +433,16 @@ public final class Unsafe } } + public void putBooleanVolatile(Object obj, long offset, boolean newValue) + { + putBoolean(obj, offset, newValue); + } + public boolean getBoolean(Object obj, long offset) { - if (obj instanceof boolean[]) + if (obj instanceof cli.System.Array) { - return ((boolean[])obj)[(int)offset]; + return Buffer.GetByte((cli.System.Array)obj, (int)offset) != 0; } else { @@ -427,11 +457,16 @@ public final class Unsafe } } + public boolean getBooleanVolatile(Object obj, long offset) + { + return getBoolean(obj, offset); + } + public void putByte(Object obj, long offset, byte newValue) { - if (obj instanceof byte[]) + if (obj instanceof cli.System.Array) { - ((byte[])obj)[(int)offset] = newValue; + Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue); } else { @@ -446,11 +481,16 @@ public final class Unsafe } } + public void putByteVolatile(Object obj, long offset, byte newValue) + { + putByte(obj, offset, newValue); + } + public byte getByte(Object obj, long offset) { - if (obj instanceof byte[]) + if (obj instanceof cli.System.Array) { - return ((byte[])obj)[(int)offset]; + return Buffer.GetByte((cli.System.Array)obj, (int)offset); } else { @@ -465,11 +505,16 @@ public final class Unsafe } } + public byte getByteVolatile(Object obj, long offset) + { + return getByte(obj, offset); + } + public void putChar(Object obj, long offset, char newValue) { - if (obj instanceof char[]) + if (obj instanceof cli.System.Array) { - ((char[])obj)[(int)offset] = newValue; + WriteInt16(obj, offset, (short)newValue); } else { @@ -484,11 +529,16 @@ public final class Unsafe } } + public void putCharVolatile(Object obj, long offset, char newValue) + { + putChar(obj, offset, newValue); + } + public char getChar(Object obj, long offset) { - if (obj instanceof char[]) + if (obj instanceof cli.System.Array) { - return ((char[])obj)[(int)offset]; + return (char)ReadInt16(obj, offset); } else { @@ -503,11 +553,16 @@ public final class Unsafe } } + public char getCharVolatile(Object obj, long offset) + { + return getChar(obj, offset); + } + public void putShort(Object obj, long offset, short newValue) { - if (obj instanceof short[]) + if (obj instanceof cli.System.Array) { - ((short[])obj)[(int)offset] = newValue; + WriteInt16(obj, offset, newValue); } else { @@ -522,11 +577,16 @@ public final class Unsafe } } + public void putShortVolatile(Object obj, long offset, short newValue) + { + putShort(obj, offset, newValue); + } + public short getShort(Object obj, long offset) { - if (obj instanceof short[]) + if (obj instanceof cli.System.Array) { - return ((short[])obj)[(int)offset]; + return ReadInt16(obj, offset); } else { @@ -541,11 +601,16 @@ public final class Unsafe } } + public short getShortVolatile(Object obj, long offset) + { + return getShort(obj, offset); + } + public void putInt(Object obj, long offset, int newValue) { - if (obj instanceof int[]) + if (obj instanceof cli.System.Array) { - ((int[])obj)[(int)offset] = newValue; + WriteInt32(obj, offset, newValue); } else { @@ -562,9 +627,9 @@ public final class Unsafe public int getInt(Object obj, long offset) { - if (obj instanceof int[]) + if (obj instanceof cli.System.Array) { - return ((int[])obj)[(int)offset]; + return ReadInt32(obj, offset); } else { @@ -581,9 +646,9 @@ public final class Unsafe public void putFloat(Object obj, long offset, float newValue) { - if (obj instanceof float[]) + if (obj instanceof cli.System.Array) { - ((float[])obj)[(int)offset] = newValue; + WriteInt32(obj, offset, Float.floatToRawIntBits(newValue)); } else { @@ -598,11 +663,16 @@ public final class Unsafe } } + public void putFloatVolatile(Object obj, long offset, float newValue) + { + putFloat(obj, offset, newValue); + } + public float getFloat(Object obj, long offset) { - if (obj instanceof float[]) + if (obj instanceof cli.System.Array) { - return ((float[])obj)[(int)offset]; + return Float.intBitsToFloat(ReadInt32(obj, offset)); } else { @@ -617,11 +687,16 @@ public final class Unsafe } } + public float getFloatVolatile(Object obj, long offset) + { + return getFloat(obj, offset); + } + public void putLong(Object obj, long offset, long newValue) { - if (obj instanceof long[]) + if (obj instanceof cli.System.Array) { - ((long[])obj)[(int)offset] = newValue; + WriteInt64(obj, offset, newValue); } else { @@ -638,9 +713,9 @@ public final class Unsafe public long getLong(Object obj, long offset) { - if (obj instanceof long[]) + if (obj instanceof cli.System.Array) { - return ((long[])obj)[(int)offset]; + return ReadInt64(obj, offset); } else { @@ -657,9 +732,9 @@ public final class Unsafe public void putDouble(Object obj, long offset, double newValue) { - if (obj instanceof double[]) + if (obj instanceof cli.System.Array) { - ((double[])obj)[(int)offset] = newValue; + WriteInt64(obj, offset, Double.doubleToRawLongBits(newValue)); } else { @@ -674,11 +749,19 @@ public final class Unsafe } } + public void putDoubleVolatile(Object obj, long offset, double newValue) + { + synchronized (this) + { + putDouble(obj, offset, newValue); + } + } + public double getDouble(Object obj, long offset) { - if (obj instanceof double[]) + if (obj instanceof cli.System.Array) { - return ((double[])obj)[(int)offset]; + return Double.longBitsToDouble(ReadInt64(obj, offset)); } else { @@ -693,6 +776,14 @@ public final class Unsafe } } + public double getDoubleVolatile(Object obj, long offset) + { + synchronized (this) + { + return getDouble(obj, offset); + } + } + public void putObject(Object obj, long offset, Object newValue) { if (obj instanceof Object[]) @@ -1122,6 +1213,10 @@ public final class Unsafe } else { + if (time == 0) + { + time = Long.MAX_VALUE; + } java.util.concurrent.locks.LockSupport.parkNanos(time); } } @@ -1136,8 +1231,16 @@ public final class Unsafe return null; } + public native boolean shouldBeInitialized(Class<?> c); + public native Class defineClass(String name, byte[] buf, int offset, int length, ClassLoader cl, ProtectionDomain pd); + @Deprecated + @sun.reflect.CallerSensitive + public native Class defineClass(String name, byte[] b, int off, int len); + + public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches); + public void monitorEnter(Object o) { cli.System.Threading.Monitor.Enter(o); @@ -1152,4 +1255,79 @@ public final class Unsafe { return cli.System.Threading.Monitor.TryEnter(o); } + + public final int getAndAddInt(Object o, long offset, int delta) + { + for (;;) + { + int value = getIntVolatile(o, offset); + if (compareAndSwapInt(o, offset, value, value + delta)) + { + return value; + } + } + } + + public final long getAndAddLong(Object o, long offset, long delta) + { + for (;;) + { + long value = getLongVolatile(o, offset); + if (compareAndSwapLong(o, offset, value, value + delta)) + { + return value; + } + } + } + + public final int getAndSetInt(Object o, long offset, int newValue) + { + for (;;) + { + int value = getIntVolatile(o, offset); + if (compareAndSwapInt(o, offset, value, newValue)) + { + return value; + } + } + } + + public final long getAndSetLong(Object o, long offset, long newValue) + { + for (;;) + { + long value = getLongVolatile(o, offset); + if (compareAndSwapLong(o, offset, value, newValue)) + { + return value; + } + } + } + + public final Object getAndSetObject(Object o, long offset, Object newValue) + { + for (;;) + { + Object value = getObjectVolatile(o, offset); + if (compareAndSwapObject(o, offset, value, newValue)) + { + return value; + } + } + } + + public void loadFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } + + public void storeFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } + + public void fullFence() + { + cli.System.Threading.Thread.MemoryBarrier(); + } } diff --git a/runtime/openjdk/sun.misc.cs b/runtime/openjdk/sun.misc.cs new file mode 100644 index 00000000..90399a86 --- /dev/null +++ b/runtime/openjdk/sun.misc.cs @@ -0,0 +1,512 @@ +/* + Copyright (C) 2007-2014 Jeroen Frijters + Copyright (C) 2009 Volker Berlin (i-net software) + + 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.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using System.Security; +using IKVM.Internal; + +static class Java_sun_misc_GC +{ + public static long maxObjectInspectionAge() + { + return 0; + } +} + +static class Java_sun_misc_MessageUtils +{ + public static void toStderr(string msg) + { + Console.Error.Write(msg); + } + + public static void toStdout(string msg) + { + Console.Out.Write(msg); + } +} + +static class Java_sun_misc_MiscHelper +{ + public static object getAssemblyClassLoader(Assembly asm, object extcl) + { + if (extcl == null || asm.IsDefined(typeof(IKVM.Attributes.CustomAssemblyClassLoaderAttribute), false)) + { + return AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader(); + } + return null; + } +} + +static class Java_sun_misc_Signal +{ + /* derived from version 6.0 VC98/include/signal.h */ + private const int SIGINT = 2; /* interrupt */ + private const int SIGILL = 4; /* illegal instruction - invalid function image */ + private const int SIGFPE = 8; /* floating point exception */ + private const int SIGSEGV = 11; /* segment violation */ + private const int SIGTERM = 15; /* Software termination signal from kill */ + private const int SIGBREAK = 21; /* Ctrl-Break sequence */ + private const int SIGABRT = 22; /* abnormal termination triggered by abort call */ + + private static Dictionary<int, long> handler = new Dictionary<int, long>(); + + // Delegate type to be used as the Handler Routine for SetConsoleCtrlHandler + private delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType); + + // Enumerated type for the control messages sent to the handler routine + private enum CtrlTypes : uint + { + CTRL_C_EVENT = 0, + CTRL_BREAK_EVENT, + CTRL_CLOSE_EVENT, + CTRL_LOGOFF_EVENT = 5, + CTRL_SHUTDOWN_EVENT + } + + [SecurityCritical] + private sealed class CriticalCtrlHandler : CriticalFinalizerObject + { + private ConsoleCtrlDelegate consoleCtrlDelegate; + private bool ok; + + [DllImport("kernel32.dll")] + private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate e, bool add); + + internal CriticalCtrlHandler() + { + consoleCtrlDelegate = new ConsoleCtrlDelegate(ConsoleCtrlCheck); + ok = SetConsoleCtrlHandler(consoleCtrlDelegate, true); + } + + [SecuritySafeCritical] + ~CriticalCtrlHandler() + { + if (ok) + { + SetConsoleCtrlHandler(consoleCtrlDelegate, false); + } + } + } + + private static object defaultConsoleCtrlDelegate; + + private static bool ConsoleCtrlCheck(CtrlTypes ctrlType) + { +#if !FIRST_PASS + switch (ctrlType) + { + case CtrlTypes.CTRL_BREAK_EVENT: + DumpAllJavaThreads(); + return true; + + } +#endif + return false; + } + +#if !FIRST_PASS + private static void DumpAllJavaThreads() + { + Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + java.util.Map traces = java.lang.Thread.getAllStackTraces(); + Console.WriteLine("Full thread dump IKVM.NET {0} ({1} bit):", JVM.SafeGetAssemblyVersion(Assembly.GetExecutingAssembly()), IntPtr.Size * 8); + java.util.Iterator entries = traces.entrySet().iterator(); + while (entries.hasNext()) + { + java.util.Map.Entry entry = (java.util.Map.Entry)entries.next(); + java.lang.Thread thread = (java.lang.Thread)entry.getKey(); + Console.WriteLine("\n\"{0}\"{1} prio={2} tid=0x{3:X8}", thread.getName(), thread.isDaemon() ? " daemon" : "", thread.getPriority(), thread.getId()); + Console.WriteLine(" java.lang.Thread.State: " + thread.getState()); + java.lang.StackTraceElement[] trace = (java.lang.StackTraceElement[])entry.getValue(); + for (int i = 0; i < trace.Length; i++) + { + Console.WriteLine("\tat {0}", trace[i]); + } + } + Console.WriteLine(); + } +#endif + + public static int findSignal(string sigName) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + switch (sigName) + { + case "ABRT": /* abnormal termination triggered by abort cl */ + return SIGABRT; + case "FPE": /* floating point exception */ + return SIGFPE; + case "SEGV": /* segment violation */ + return SIGSEGV; + case "INT": /* interrupt */ + return SIGINT; + case "TERM": /* software term signal from kill */ + return SIGTERM; + case "BREAK": /* Ctrl-Break sequence */ + return SIGBREAK; + case "ILL": /* illegal instruction */ + return SIGILL; + } + } + return -1; + } + + // this is a separate method to be able to catch the SecurityException (for the LinkDemand) + [SecuritySafeCritical] + private static void RegisterCriticalCtrlHandler() + { + defaultConsoleCtrlDelegate = new CriticalCtrlHandler(); + } + + // Register a signal handler + public static long handle0(int sig, long nativeH) + { + long oldHandler; + handler.TryGetValue(sig, out oldHandler); + switch (nativeH) + { + case 0: // Default Signal Handler + if (defaultConsoleCtrlDelegate == null && Environment.OSVersion.Platform == PlatformID.Win32NT) + { + try + { + RegisterCriticalCtrlHandler(); + } + catch (SecurityException) + { + } + } + break; + case 1: // Ignore Signal + break; + case 2: // Custom Signal Handler + switch (sig) + { + case SIGBREAK: + case SIGFPE: + return -1; + } + break; + } + handler[sig] = nativeH; + return oldHandler; + } + + public static void raise0(int sig) + { +#if !FIRST_PASS + java.security.AccessController.doPrivileged(ikvm.runtime.Delegates.toPrivilegedAction(delegate + { + java.lang.Class clazz = typeof(sun.misc.Signal); + java.lang.reflect.Method dispatch = clazz.getDeclaredMethod("dispatch", java.lang.Integer.TYPE); + dispatch.setAccessible(true); + dispatch.invoke(null, java.lang.Integer.valueOf(sig)); + return null; + })); +#endif + } +} + +static class Java_sun_misc_NativeSignalHandler +{ + public static void handle0(int number, long handler) + { + throw new NotImplementedException(); + } +} + +static class Java_sun_misc_Perf +{ + public static object attach(object thisPerf, string user, int lvmid, int mode) + { + throw new NotImplementedException(); + } + + public static void detach(object thisPerf, object bb) + { + throw new NotImplementedException(); + } + + public static object createLong(object thisPerf, string name, int variability, int units, long value) + { +#if FIRST_PASS + return null; +#else + return java.nio.ByteBuffer.allocate(8); +#endif + } + + public static object createByteArray(object thisPerf, string name, int variability, int units, byte[] value, int maxLength) + { +#if FIRST_PASS + return null; +#else + return java.nio.ByteBuffer.allocate(maxLength).put(value); +#endif + } + + public static long highResCounter(object thisPerf) + { + throw new NotImplementedException(); + } + + public static long highResFrequency(object thisPerf) + { + throw new NotImplementedException(); + } + + public static void registerNatives() + { + } +} + +static class Java_sun_misc_Unsafe +{ + private static void CheckArrayBounds(object obj, long offset, int accessLength) + { + // NOTE we rely on the fact that Buffer.ByteLength() requires a primitive array + int arrayLength = Buffer.ByteLength((Array)obj); + if (offset < 0 || offset > arrayLength - accessLength || accessLength > arrayLength) + { + throw new IndexOutOfRangeException(); + } + } + + [SecuritySafeCritical] + public static short ReadInt16(object obj, long offset) + { + CheckArrayBounds(obj, offset, 2); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + short value = Marshal.ReadInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset)); + handle.Free(); + return value; + } + + [SecuritySafeCritical] + public static int ReadInt32(object obj, long offset) + { + CheckArrayBounds(obj, offset, 4); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + int value = Marshal.ReadInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset)); + handle.Free(); + return value; + } + + [SecuritySafeCritical] + public static long ReadInt64(object obj, long offset) + { + CheckArrayBounds(obj, offset, 8); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + long value = Marshal.ReadInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset)); + handle.Free(); + return value; + } + + [SecuritySafeCritical] + public static void WriteInt16(object obj, long offset, short value) + { + CheckArrayBounds(obj, offset, 2); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + Marshal.WriteInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value); + handle.Free(); + } + + [SecuritySafeCritical] + public static void WriteInt32(object obj, long offset, int value) + { + CheckArrayBounds(obj, offset, 4); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + Marshal.WriteInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value); + handle.Free(); + } + + [SecuritySafeCritical] + public static void WriteInt64(object obj, long offset, long value) + { + CheckArrayBounds(obj, offset, 8); + GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned); + Marshal.WriteInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value); + handle.Free(); + } + + public static void throwException(object thisUnsafe, Exception x) + { + throw x; + } + + public static bool shouldBeInitialized(object thisUnsafe, java.lang.Class clazz) + { + return TypeWrapper.FromClass(clazz).HasStaticInitializer; + } + + public static void ensureClassInitialized(object thisUnsafe, java.lang.Class clazz) + { + TypeWrapper tw = TypeWrapper.FromClass(clazz); + if (!tw.IsArray) + { + try + { + tw.Finish(); + } + catch (RetargetableJavaException x) + { + throw x.ToJava(); + } + tw.RunClassInit(); + } + } + + [SecurityCritical] + public static object allocateInstance(object thisUnsafe, java.lang.Class clazz) + { + TypeWrapper wrapper = TypeWrapper.FromClass(clazz); + try + { + wrapper.Finish(); + } + catch (RetargetableJavaException x) + { + throw x.ToJava(); + } + return FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType); + } + + public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, java.lang.ClassLoader cl, java.security.ProtectionDomain pd) + { + return Java_java_lang_ClassLoader.defineClass1(cl, name.Replace('/', '.'), buf, offset, length, pd, null); + } + + public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, ikvm.@internal.CallerID callerID) + { +#if FIRST_PASS + return null; +#else + return defineClass(thisUnsafe, name, buf, offset, length, callerID.getCallerClassLoader(), callerID.getCallerClass().pd); +#endif + } + + public static java.lang.Class defineAnonymousClass(object thisUnsafe, java.lang.Class host, byte[] data, object[] cpPatches) + { +#if FIRST_PASS + return null; +#else + try + { + ClassLoaderWrapper loader = TypeWrapper.FromClass(host).GetClassLoader(); + ClassFile classFile = new ClassFile(data, 0, data.Length, "<Unknown>", loader.ClassFileParseOptions, cpPatches); + if (classFile.IKVMAssemblyAttribute != null) + { + // if this happens, the OpenJDK is probably trying to load an OpenJDK class file as a resource, + // make sure the build process includes the original class file as a resource in that case + throw new java.lang.ClassFormatError("Trying to define anonymous class based on stub class: " + classFile.Name); + } + return loader.GetTypeWrapperFactory().DefineClassImpl(null, TypeWrapper.FromClass(host), classFile, loader, host.pd).ClassObject; + } + catch (RetargetableJavaException x) + { + throw x.ToJava(); + } +#endif + } +} + +static class Java_sun_misc_Version +{ + public static string getJvmSpecialVersion() + { + throw new NotImplementedException(); + } + + public static string getJdkSpecialVersion() + { + throw new NotImplementedException(); + } + + public static bool getJvmVersionInfo() + { + throw new NotImplementedException(); + } + + public static void getJdkVersionInfo() + { + throw new NotImplementedException(); + } +} + +static class Java_sun_misc_VM +{ + public static void initialize() + { + } + + public static java.lang.ClassLoader latestUserDefinedLoader() + { + // testing shows that it is cheaper the get the full stack trace and then look at a few frames than getting the frames individually + StackTrace trace = new StackTrace(2, false); + for (int i = 0; i < trace.FrameCount; i++) + { + StackFrame frame = trace.GetFrame(i); + MethodBase method = frame.GetMethod(); + if (method == null) + { + continue; + } + Type type = method.DeclaringType; + if (type != null) + { + TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type); + if (tw != null) + { + ClassLoaderWrapper classLoader = tw.GetClassLoader(); + AssemblyClassLoader acl = classLoader as AssemblyClassLoader; + if (acl == null || acl.GetAssembly(tw) != typeof(object).Assembly) + { + java.lang.ClassLoader javaClassLoader = classLoader.GetJavaClassLoader(); + if (javaClassLoader != null) + { + return javaClassLoader; + } + } + } + } + } + return null; + } +} + +static class Java_sun_misc_VMSupport +{ + public static object initAgentProperties(object props) + { + return props; + } +} |