sun.misc.Unsafe Maven / Gradle / Ivy
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sun.misc;
import dalvik.system.VMStack;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* The package name notwithstanding, this class is the quasi-standard
* way for Java code to gain access to and use functionality which,
* when unsupervised, would allow one to break the pointer/type safety
* of Java.
*/
public final class Unsafe {
/** Traditional dalvik name. */
private static final Unsafe THE_ONE = new Unsafe();
/** Traditional RI name. */
private static final Unsafe theUnsafe = THE_ONE;
/**
* This class is only privately instantiable.
*/
private Unsafe() {}
/**
* Gets the unique instance of this class. This is only allowed in
* very limited situations.
*/
public static Unsafe getUnsafe() {
/*
* Only code on the bootclasspath is allowed to get at the
* Unsafe instance.
*/
ClassLoader calling = VMStack.getCallingClassLoader();
if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
throw new SecurityException("Unsafe access denied");
}
return THE_ONE;
}
/**
* Gets the raw byte offset from the start of an object's memory to
* the memory used to store the indicated instance field.
*
* @param field non-null; the field in question, which must be an
* instance field
* @return the offset to the field
*/
public long objectFieldOffset(Field field) {
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalArgumentException(
"valid for instance fields only");
}
return objectFieldOffset0(field);
}
/**
* Helper for {@link #objectFieldOffset}, which does all the work,
* assuming the parameter is deemed valid.
*
* @param field non-null; the instance field
* @return the offset to the field
*/
private static native long objectFieldOffset0(Field field);
/**
* Gets the offset from the start of an array object's memory to
* the memory used to store its initial (zeroeth) element.
*
* @param clazz non-null; class in question; must be an array class
* @return the offset to the initial element
*/
public int arrayBaseOffset(Class clazz) {
if (! clazz.isArray()) {
throw new IllegalArgumentException(
"valid for array classes only");
}
return arrayBaseOffset0(clazz);
}
/**
* Helper for {@link #arrayBaseOffset}, which does all the work,
* assuming the parameter is deemed valid.
*
* @return the offset to the field
*/
private static native int arrayBaseOffset0(Class clazz);
/**
* Gets the size of each element of the given array class.
*
* @param clazz non-null; class in question; must be an array class
* @return > 0; the size of each element of the array
*/
public int arrayIndexScale(Class clazz) {
if (! clazz.isArray()) {
throw new IllegalArgumentException(
"valid for array classes only");
}
return arrayIndexScale0(clazz);
}
/**
* Helper for {@link #arrayIndexScale}, which does all the work,
* assuming the parameter is deemed valid.
*
* @return the offset to the field
*/
private static native int arrayIndexScale0(Class clazz);
/**
* Performs a compare-and-set operation on an int
* field within the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param expectedValue expected value of the field
* @param newValue new value to store in the field if the contents are
* as expected
* @return true
if the new value was in fact stored, and
* false
if not
*/
public native boolean compareAndSwapInt(Object obj, long offset,
int expectedValue, int newValue);
/**
* Performs a compare-and-set operation on a long
* field within the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param expectedValue expected value of the field
* @param newValue new value to store in the field if the contents are
* as expected
* @return true
if the new value was in fact stored, and
* false
if not
*/
public native boolean compareAndSwapLong(Object obj, long offset,
long expectedValue, long newValue);
/**
* Performs a compare-and-set operation on an Object
* field (that is, a reference field) within the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param expectedValue expected value of the field
* @param newValue new value to store in the field if the contents are
* as expected
* @return true
if the new value was in fact stored, and
* false
if not
*/
public native boolean compareAndSwapObject(Object obj, long offset,
Object expectedValue, Object newValue);
/**
* Gets an int
field from the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native int getIntVolatile(Object obj, long offset);
/**
* Stores an int
field into the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putIntVolatile(Object obj, long offset, int newValue);
/**
* Gets a long
field from the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native long getLongVolatile(Object obj, long offset);
/**
* Stores a long
field into the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putLongVolatile(Object obj, long offset, long newValue);
/**
* Gets an Object
field from the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native Object getObjectVolatile(Object obj, long offset);
/**
* Stores an Object
field into the given object,
* using volatile
semantics.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putObjectVolatile(Object obj, long offset,
Object newValue);
/**
* Gets an int
field from the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native int getInt(Object obj, long offset);
/**
* Stores an int
field into the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putInt(Object obj, long offset, int newValue);
/**
* Lazy set an int field.
*/
public native void putOrderedInt(Object obj, long offset, int newValue);
/**
* Gets a long
field from the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native long getLong(Object obj, long offset);
/**
* Stores a long
field into the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putLong(Object obj, long offset, long newValue);
/**
* Lazy set a long field.
*/
public native void putOrderedLong(Object obj, long offset, long newValue);
/**
* Gets an Object
field from the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @return the retrieved value
*/
public native Object getObject(Object obj, long offset);
/**
* Stores an Object
field into the given object.
*
* @param obj non-null; object containing the field
* @param offset offset to the field within obj
* @param newValue the value to store
*/
public native void putObject(Object obj, long offset, Object newValue);
/**
* Lazy set an object field.
*/
public native void putOrderedObject(Object obj, long offset,
Object newValue);
/**
* Parks the calling thread for the specified amount of time,
* unless the "permit" for the thread is already available (due to
* a previous call to {@link #unpark}. This method may also return
* spuriously (that is, without the thread being told to unpark
* and without the indicated amount of time elapsing).
*
* See {@link java.util.concurrent.locks.LockSupport} for more
* in-depth information of the behavior of this method.
*
* @param absolute whether the given time value is absolute
* milliseconds-since-the-epoch (true
) or relative
* nanoseconds-from-now (false
)
* @param time the (absolute millis or relative nanos) time value
*/
public void park(boolean absolute, long time) {
if (absolute) {
Thread.currentThread().parkUntil(time);
} else {
Thread.currentThread().parkFor(time);
}
}
/**
* Unparks the given object, which must be a {@link Thread}.
*
* See {@link java.util.concurrent.locks.LockSupport} for more
* in-depth information of the behavior of this method.
*
* @param obj non-null; the object to unpark
*/
public void unpark(Object obj) {
if (obj instanceof Thread) {
((Thread) obj).unpark();
} else {
throw new IllegalArgumentException("valid for Threads only");
}
}
/**
* Allocates an instance of the given class without running the constructor.
* The class' will be run, if necessary.
*/
public native Object allocateInstance(Class> c);
}