summaryrefslogtreecommitdiffstats
path: root/libart/src/main/java/sun/misc/Unsafe.java
diff options
context:
space:
mode:
Diffstat (limited to 'libart/src/main/java/sun/misc/Unsafe.java')
-rw-r--r--libart/src/main/java/sun/misc/Unsafe.java338
1 files changed, 338 insertions, 0 deletions
diff --git a/libart/src/main/java/sun/misc/Unsafe.java b/libart/src/main/java/sun/misc/Unsafe.java
new file mode 100644
index 0000000..aa7b6de
--- /dev/null
+++ b/libart/src/main/java/sun/misc/Unsafe.java
@@ -0,0 +1,338 @@
+/*
+ * 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 field.getOffset();
+ }
+
+ /**
+ * 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) {
+ Class<?> component = clazz.getComponentType();
+ if (component == null) {
+ throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+ }
+ // TODO: make the following not specific to the object model.
+ int offset = 12;
+ if (component == long.class || component == double.class) {
+ offset += 4; // 4 bytes of padding.
+ }
+ return offset;
+ }
+
+ /**
+ * Gets the size of each element of the given array class.
+ *
+ * @param clazz non-null; class in question; must be an array class
+ * @return &gt; 0; the size of each element of the array
+ */
+ public int arrayIndexScale(Class clazz) {
+ Class<?> component = clazz.getComponentType();
+ if (component == null) {
+ throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+ }
+ // TODO: make the following not specific to the object model.
+ if (!clazz.isPrimitive()) {
+ return 4;
+ } else if (component == long.class || component == double.class) {
+ return 8;
+ } else if (component == int.class || component == float.class) {
+ return 4;
+ } else if (component == char.class || component == short.class) {
+ return 2;
+ } else {
+ // component == byte.class || component == boolean.class.
+ return 1;
+ }
+ }
+
+ /**
+ * Performs a compare-and-set operation on an <code>int</code>
+ * field within the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapInt(Object obj, long offset,
+ int expectedValue, int newValue);
+
+ /**
+ * Performs a compare-and-set operation on a <code>long</code>
+ * field within the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapLong(Object obj, long offset,
+ long expectedValue, long newValue);
+
+ /**
+ * Performs a compare-and-set operation on an <code>Object</code>
+ * 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 <code>obj</code>
+ * @param expectedValue expected value of the field
+ * @param newValue new value to store in the field if the contents are
+ * as expected
+ * @return <code>true</code> if the new value was in fact stored, and
+ * <code>false</code> if not
+ */
+ public native boolean compareAndSwapObject(Object obj, long offset,
+ Object expectedValue, Object newValue);
+
+ /**
+ * Gets an <code>int</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native int getIntVolatile(Object obj, long offset);
+
+ /**
+ * Stores an <code>int</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putIntVolatile(Object obj, long offset, int newValue);
+
+ /**
+ * Gets a <code>long</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native long getLongVolatile(Object obj, long offset);
+
+ /**
+ * Stores a <code>long</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putLongVolatile(Object obj, long offset, long newValue);
+
+ /**
+ * Gets an <code>Object</code> field from the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native Object getObjectVolatile(Object obj, long offset);
+
+ /**
+ * Stores an <code>Object</code> field into the given object,
+ * using <code>volatile</code> semantics.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @param newValue the value to store
+ */
+ public native void putObjectVolatile(Object obj, long offset,
+ Object newValue);
+
+ /**
+ * Gets an <code>int</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native int getInt(Object obj, long offset);
+
+ /**
+ * Stores an <code>int</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @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 <code>long</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native long getLong(Object obj, long offset);
+
+ /**
+ * Stores a <code>long</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @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 <code>Object</code> field from the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @return the retrieved value
+ */
+ public native Object getObject(Object obj, long offset);
+
+ /**
+ * Stores an <code>Object</code> field into the given object.
+ *
+ * @param obj non-null; object containing the field
+ * @param offset offset to the field within <code>obj</code>
+ * @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).
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * @param absolute whether the given time value is absolute
+ * milliseconds-since-the-epoch (<code>true</code>) or relative
+ * nanoseconds-from-now (<code>false</code>)
+ * @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}.
+ *
+ * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+ * in-depth information of the behavior of this method.</p>
+ *
+ * @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' <clinit> will be run, if necessary.
+ */
+ public native Object allocateInstance(Class<?> c);
+}