ikvm-fork/openjdk/sun/misc/Unsafe.java

393 строки
8.9 KiB
Java

/*
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 sun.misc;
import gnu.classpath.VMStackWalker;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.reflect.ReflectionFactory;
public final class Unsafe
{
private static final Unsafe instance = new Unsafe();
private static final ArrayList<Field> fields = new ArrayList<Field>();
private static final ReflectionFactory factory = (ReflectionFactory)AccessController.doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());
private Unsafe() {}
public static Unsafe getUnsafe()
{
if(VMStackWalker.getCallingClassLoader() != null)
{
throw new SecurityException();
}
return instance;
}
// NOTE we have a really lame (and slow) implementation!
public long objectFieldOffset(Field field)
{
return fieldOffset(field);
}
public int fieldOffset(Field original)
{
final Field copy = factory.copyField(original);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
copy.setAccessible(true);
return null;
}
});
synchronized(fields)
{
int id = fields.size();
fields.add(copy);
return id;
}
}
public int arrayBaseOffset(Class c)
{
return 0;
}
public int arrayIndexScale(Class c)
{
return 1;
}
private static Field getField(long offset)
{
synchronized(fields)
{
return fields.get((int)offset);
}
}
public boolean compareAndSwapObject(Object obj, long offset, Object expect, Object update)
{
if(obj instanceof Object[])
{
Object[] arr = (Object[])obj;
int index = (int)offset;
synchronized(this)
{
if(arr[index] == expect)
{
arr[index] = update;
return true;
}
return false;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
if(field.get(obj) == expect)
{
field.set(obj, update);
return true;
}
return false;
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putObjectVolatile(Object obj, long offset, Object newValue)
{
if(obj instanceof Object[])
{
synchronized(this)
{
((Object[])obj)[(int)offset] = newValue;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
field.set(obj, newValue);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putOrderedObject(Object obj, long offset, Object newValue)
{
putObjectVolatile(obj, offset, newValue);
}
public Object getObjectVolatile(Object obj, long offset)
{
if(obj instanceof Object[])
{
synchronized(this)
{
return ((Object[])obj)[(int)offset];
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
return field.get(obj);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public boolean compareAndSwapInt(Object obj, long offset, int expect, int update)
{
if(obj instanceof int[])
{
int[] arr = (int[])obj;
int index = (int)offset;
synchronized(this)
{
if(arr[index] == expect)
{
arr[index] = update;
return true;
}
return false;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
if(field.getInt(obj) == expect)
{
field.setInt(obj, update);
return true;
}
return false;
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putIntVolatile(Object obj, long offset, int newValue)
{
if(obj instanceof int[])
{
synchronized(this)
{
((int[])obj)[(int)offset] = newValue;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
field.setInt(obj, newValue);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putOrderedInt(Object obj, long offset, int newValue)
{
putIntVolatile(obj, offset, newValue);
}
public int getIntVolatile(Object obj, long offset)
{
if(obj instanceof int[])
{
synchronized(this)
{
return ((int[])obj)[(int)offset];
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
return field.getInt(obj);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public boolean compareAndSwapLong(Object obj, long offset, long expect, long update)
{
if(obj instanceof long[])
{
long[] arr = (long[])obj;
int index = (int)offset;
synchronized(this)
{
if(arr[index] == expect)
{
arr[index] = update;
return true;
}
return false;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
if(field.getLong(obj) == expect)
{
field.setLong(obj, update);
return true;
}
return false;
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putLongVolatile(Object obj, long offset, long newValue)
{
if(obj instanceof long[])
{
synchronized(this)
{
((long[])obj)[(int)offset] = newValue;
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
field.setLong(obj, newValue);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putOrderedLong(Object obj, long offset, long newValue)
{
putLongVolatile(obj, offset, newValue);
}
public long getLongVolatile(Object obj, long offset)
{
if(obj instanceof long[])
{
synchronized(this)
{
return ((long[])obj)[(int)offset];
}
}
else
{
Field field = getField(offset);
synchronized(field)
{
try
{
return field.getLong(obj);
}
catch(IllegalAccessException x)
{
throw (InternalError)new InternalError().initCause(x);
}
}
}
}
public void putLong(Object obj, long offset, long newValue)
{
putLongVolatile(obj, offset, newValue);
}
public long getLong(Object obj, long offset)
{
return getLongVolatile(obj, offset);
}
public native void throwException(Throwable t);
public native void ensureClassInitialized(Class clazz);
public native Object allocateInstance(Class clazz) throws InstantiationException;
}