summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2006-03-20 00:32:54 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2006-03-20 00:32:54 +0000
commit4f1902554ebf0c2f6bddcf099851be09eef346b0 (patch)
treeb58fb9be832680554116d7d8458ff5ac12e6c364
parentb2a543058a0bf760fbfd9a964819db82ab01d50d (diff)
downloadclasspath-4f1902554ebf0c2f6bddcf099851be09eef346b0.tar.gz
2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
* java/lang/System.java: (nanoTime()): Documented. * java/lang/Thread.java: (setUncaughtExceptionHandler(UncaughtExceptionHandler): Added docs and security check. (getUncaughtExceptionHandler()): Documented. (setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler): Added docs and security check. (getDefaultUncaughtExceptionHandler()): Documented. (getId()): Documented. (Thread.State): Documented. * vm/reference/gnu/classpath/Unsafe.java: Documented. (getUnsafe()): Updated to handle security. 2006-03-20 Tom Tromey <tromey@redhat.com> * java/lang/System.java: (nanoTime()): Implemented. * java/lang/Thread.java: (getId()): Implemented. * java/util/AbstractMap.java: (SimpleImmutableEntry): New 1.6 class. (BasicMapEntry): Modified to be SimpleEntry. * java/util/Collections.java: Modified to use SimpleEntry. * java/util/EnumMap.java: Likewise. * java/util/HashMap.java: Likewise. * java/util/Hashtable.java: Likewise. * java/util/TreeMap.java: Likewise. * vm/reference/gnu/classpath/Unsafe.java: New class to handle low-level facilities for concurrency. * vm/reference/java/lang/VMSystem.java: (nanoTime()): Implemented.
-rw-r--r--ChangeLog37
-rw-r--r--java/lang/System.java30
-rw-r--r--java/lang/Thread.java120
-rw-r--r--java/util/AbstractMap.java61
-rw-r--r--java/util/Collections.java2
-rw-r--r--java/util/EnumMap.java2
-rw-r--r--java/util/HashMap.java8
-rw-r--r--java/util/Hashtable.java8
-rw-r--r--java/util/TreeMap.java2
-rw-r--r--vm/reference/gnu/classpath/Unsafe.java328
-rw-r--r--vm/reference/java/lang/VMSystem.java5
11 files changed, 577 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index f4e7e77d1..a5ee63be5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2006-03-20 Andrew John Hughes <gnu_andrew@member.fsf.org>
+
+ * java/lang/System.java:
+ (nanoTime()): Documented.
+ * java/lang/Thread.java:
+ (setUncaughtExceptionHandler(UncaughtExceptionHandler):
+ Added docs and security check.
+ (getUncaughtExceptionHandler()): Documented.
+ (setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler):
+ Added docs and security check.
+ (getDefaultUncaughtExceptionHandler()): Documented.
+ (getId()): Documented.
+ (Thread.State): Documented.
+ * vm/reference/gnu/classpath/Unsafe.java:
+ Documented.
+ (getUnsafe()): Updated to handle security.
+
+2006-03-20 Tom Tromey <tromey@redhat.com>
+
+ * java/lang/System.java:
+ (nanoTime()): Implemented.
+ * java/lang/Thread.java:
+ (getId()): Implemented.
+ * java/util/AbstractMap.java:
+ (SimpleImmutableEntry): New 1.6 class.
+ (BasicMapEntry): Modified to be SimpleEntry.
+ * java/util/Collections.java:
+ Modified to use SimpleEntry.
+ * java/util/EnumMap.java: Likewise.
+ * java/util/HashMap.java: Likewise.
+ * java/util/Hashtable.java: Likewise.
+ * java/util/TreeMap.java: Likewise.
+ * vm/reference/gnu/classpath/Unsafe.java:
+ New class to handle low-level facilities for concurrency.
+ * vm/reference/java/lang/VMSystem.java:
+ (nanoTime()): Implemented.
+
2006-03-13 Tom Tromey <tromey@redhat.com>
* javax/swing/text/html/StyleSheet.java (removeAttributes):
diff --git a/java/lang/System.java b/java/lang/System.java
index 1fb59794f..c0d897354 100644
--- a/java/lang/System.java
+++ b/java/lang/System.java
@@ -233,6 +233,36 @@ public final class System
{
return VMSystem.currentTimeMillis();
}
+
+ /**
+ * <p>
+ * Returns the current value of a nanosecond-precise system timer.
+ * The value of the timer is an offset relative to some arbitrary fixed
+ * time, which may be in the future (making the value negative). This
+ * method is useful for timing events where nanosecond precision is
+ * required. This is achieved by calling this method before and after the
+ * event, and taking the difference betweent the two times:
+ * </p>
+ * <p>
+ * <code>long startTime = System.nanoTime();</code><br />
+ * <code>... <emph>event code</emph> ...</code><br />
+ * <code>long endTime = System.nanoTime();</code><br />
+ * <code>long duration = endTime - startTime;</code><br />
+ * </p>
+ * <p>
+ * Note that the value is only nanosecond-precise, and not accurate; there
+ * is no guarantee that the difference between two values is really a
+ * nanosecond. Also, the value is prone to overflow if the offset
+ * exceeds 2^63.
+ * </p>
+ *
+ * @return the time of a system timer in nanoseconds.
+ * @since 1.5
+ */
+ public static long nanoTime()
+ {
+ return VMSystem.nanoTime();
+ }
/**
* Copy one array onto another from <code>src[srcStart]</code> ...
diff --git a/java/lang/Thread.java b/java/lang/Thread.java
index 398a3864b..b4ebd58e4 100644
--- a/java/lang/Thread.java
+++ b/java/lang/Thread.java
@@ -131,9 +131,18 @@ public class Thread implements Runnable
/** The context classloader for this Thread. */
private ClassLoader contextClassLoader;
+
+ /** This thread's ID. */
+ private final long threadId;
+
+ /** The park blocker. See LockSupport. */
+ Object parkBlocker;
/** The next thread number to use. */
private static int numAnonymousThreadsCreated;
+
+ /** The next thread ID to use. */
+ private static long nextThreadId;
/** The default exception handler. */
private static UncaughtExceptionHandler defaultHandler;
@@ -349,6 +358,11 @@ public class Thread implements Runnable
this.name = name.toString();
this.runnable = target;
this.stacksize = size;
+
+ synchronized (Thread.class)
+ {
+ this.threadId = nextThreadId++;
+ }
priority = current.priority;
daemon = current.daemon;
@@ -378,6 +392,10 @@ public class Thread implements Runnable
this.priority = priority;
this.daemon = daemon;
this.contextClassLoader = ClassLoader.getSystemClassLoader();
+ synchronized (Thread.class)
+ {
+ this.threadId = nextThreadId++;
+ }
}
/**
@@ -1020,29 +1038,100 @@ public class Thread implements Runnable
return locals;
}
- /** @since 1.5 */
+ /**
+ * Assigns the given <code>UncaughtExceptionHandler</code> to this
+ * thread. This will then be called if the thread terminates due
+ * to an uncaught exception, pre-empting that of the
+ * <code>ThreadGroup</code>.
+ *
+ * @param h the handler to use for this thread.
+ * @throws SecurityException if the current thread can't modify this thread.
+ * @since 1.5
+ */
public void setUncaughtExceptionHandler(UncaughtExceptionHandler h)
{
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkAccess(this);
exceptionHandler = h;
}
- /** @since 1.5 */
+ /**
+ * <p>
+ * Returns the handler used when this thread terminates due to an
+ * uncaught exception. The handler used is determined by the following:
+ * </p>
+ * <ul>
+ * <li>If this thread has its own handler, this is returned.</li>
+ * <li>If not, then the handler of the thread's <code>ThreadGroup</code>
+ * object is returned.</li>
+ * <li>If both are unavailable, then <code>null</code> is returned.</li>
+ * </ul>
+ *
+ * @return the appropriate <code>UncaughtExceptionHandler</code> or
+ * <code>null</code> if one can't be obtained.
+ * @since 1.5
+ */
public UncaughtExceptionHandler getUncaughtExceptionHandler()
{
return exceptionHandler;
}
- /** @since 1.5 */
- public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler h)
+ /**
+ * <p>
+ * Sets the default uncaught exception handler used when one isn't
+ * provided by the thread or its associated <code>ThreadGroup</code>.
+ * This exception handler is used when the thread itself does not
+ * have an exception handler, and the thread's <code>ThreadGroup</code>
+ * does not override this default mechanism with its own. As the group
+ * calls this handler by default, this exception handler should not defer
+ * to that of the group, as it may lead to infinite recursion.
+ * </p>
+ * <p>
+ * Uncaught exception handlers are used when a thread terminates due to
+ * an uncaught exception. Replacing this handler allows default code to
+ * be put in place for all threads in order to handle this eventuality.
+ * </p>
+ *
+ * @param h the new default uncaught exception handler to use.
+ * @throws SecurityException if a security manager is present and
+ * disallows the runtime permission
+ * "setDefaultUncaughtExceptionHandler".
+ * @since 1.5
+ */
+ public static void
+ setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler h)
{
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
defaultHandler = h;
}
- /** @since 1.5 */
+ /**
+ * Returns the handler used by default when a thread terminates
+ * unexpectedly due to an exception, or <code>null</code> if one doesn't
+ * exist.
+ *
+ * @return the default uncaught exception handler.
+ * @since 1.5
+ */
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler()
{
return defaultHandler;
}
+
+ /**
+ * Returns the unique identifier for this thread. This ID is generated
+ * on thread creation, and may be re-used on its death.
+ *
+ * @return a positive long number representing the thread's ID.
+ * @since 1.5
+ */
+ public long getId()
+ {
+ return threadId;
+ }
/**
* <p>
@@ -1102,7 +1191,26 @@ public class Thread implements Runnable
void uncaughtException(Thread thr, Throwable exc);
}
- /** @since 1.5 */
+ /**
+ * <p>
+ * Represents the current state of a thread, according to the VM rather
+ * than the operating system. It can be one of the following:
+ * </p>
+ * <ul>
+ * <li>NEW -- The thread has just been created but is not yet running.</li>
+ * <li>RUNNABLE -- The thread is currently running or can be scheduled
+ * to run.</li>
+ * <li>BLOCKED -- The thread is blocked waiting on an I/O operation
+ * or to obtain a lock.</li>
+ * <li>WAITING -- The thread is waiting indefinately for another thread
+ * to do something.</li>
+ * <li>TIMED_WAITING -- The thread is waiting for a specific amount of time
+ * for another thread to do something.</li>
+ * <li>TERMINATED -- The thread has exited.</li>
+ * </ul>
+ *
+ * @since 1.5
+ */
public enum State
{
BLOCKED, NEW, RUNNABLE, TERMINATED, TIMED_WAITING, WAITING;
diff --git a/java/util/AbstractMap.java b/java/util/AbstractMap.java
index 9b543b026..29249e1dc 100644
--- a/java/util/AbstractMap.java
+++ b/java/util/AbstractMap.java
@@ -39,6 +39,8 @@ exception statement from your version. */
package java.util;
+import java.io.Serializable;
+
/**
* An abstract implementation of Map to make it easier to create your own
* implementations. In order to create an unmodifiable Map, subclass
@@ -67,7 +69,41 @@ package java.util;
*/
public abstract class AbstractMap<K, V> implements Map<K, V>
{
- /** An "enum" of iterator types. */
+ /** @since 1.6 */
+ public static class SimpleImmutableEntry<K, V>
+ implements Entry<K, V>, Serializable
+ {
+ K key;
+ V value;
+
+ public SimpleImmutableEntry(K key, V value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry)
+ {
+ this(entry.getKey(), entry.getValue());
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public V getValue()
+ {
+ return value;
+ }
+
+ public V setValue(V value)
+ {
+ throw new UnsupportedOperationException("setValue not supported on immutable entry");
+ }
+ }
+
+/** An "enum" of iterator types. */
// Package visible for use by subclasses.
static final int KEYS = 0,
VALUES = 1,
@@ -629,10 +665,10 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
*
* @author Jon Zeppieri
* @author Eric Blake (ebb9@email.byu.edu)
+ *
+ * @since 1.6
*/
- // XXX - FIXME Use fully qualified implements as gcj 3.1 workaround.
- // Bug still exists in 3.4.1
- static class BasicMapEntry<K, V> implements Map.Entry<K, V>
+ public static class SimpleEntry<K, V> implements Entry<K, V>, Serializable
{
/**
* The key. Package visible for direct manipulation.
@@ -649,11 +685,16 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
* @param newKey the key
* @param newValue the value
*/
- BasicMapEntry(K newKey, V newValue)
+ public SimpleEntry(K newKey, V newValue)
{
key = newKey;
value = newValue;
}
+
+ public SimpleEntry(Entry<? extends K, ? extends V> entry)
+ {
+ this(entry.getKey(), entry.getValue());
+ }
/**
* Compares the specified object with this entry. Returns true only if
@@ -668,14 +709,14 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
* @param o the object to compare
* @return <code>true</code> if it is equal
*/
- public final boolean equals(Object o)
+ public boolean equals(Object o)
{
if (! (o instanceof Map.Entry))
return false;
// Optimize for our own entries.
- if (o instanceof BasicMapEntry)
+ if (o instanceof SimpleEntry)
{
- BasicMapEntry e = (BasicMapEntry) o;
+ SimpleEntry e = (SimpleEntry) o;
return (AbstractMap.equals(key, e.key)
&& AbstractMap.equals(value, e.value));
}
@@ -751,5 +792,7 @@ public abstract class AbstractMap<K, V> implements Map<K, V>
{
return key + "=" + value;
}
- } // class BasicMapEntry
+ } // class SimpleEntry
+
+
}
diff --git a/java/util/Collections.java b/java/util/Collections.java
index 6cf21a53b..29ee4dfe6 100644
--- a/java/util/Collections.java
+++ b/java/util/Collections.java
@@ -1943,7 +1943,7 @@ public class Collections
{
if (entries == null)
{
- Map.Entry<K,V> entry = new AbstractMap.BasicMapEntry<K, V>(k, v)
+ Map.Entry<K,V> entry = new AbstractMap.SimpleEntry<K, V>(k, v)
{
/**
* Sets the value of the map entry to the supplied value.
diff --git a/java/util/EnumMap.java b/java/util/EnumMap.java
index 31c003d61..477dff8e0 100644
--- a/java/util/EnumMap.java
+++ b/java/util/EnumMap.java
@@ -329,7 +329,7 @@ public class EnumMap<K extends Enum<K>, V>
;
// FIXME: we could just return something that
// only knows the index. That would be cleaner.
- return new AbstractMap.BasicMapEntry<K, V>(enumClass.getEnumConstants()[index],
+ return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
store[index])
{
public V setValue(V newVal)
diff --git a/java/util/HashMap.java b/java/util/HashMap.java
index 2ce74becc..715569a3f 100644
--- a/java/util/HashMap.java
+++ b/java/util/HashMap.java
@@ -162,7 +162,7 @@ public class HashMap<K, V> extends AbstractMap<K, V>
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- static class HashEntry<K, V> extends AbstractMap.BasicMapEntry<K, V>
+ static class HashEntry<K, V> extends AbstractMap.SimpleEntry<K, V>
{
/**
* The next entry in the linked list. Package visible for use by subclass.
@@ -386,10 +386,10 @@ public class HashMap<K, V> extends AbstractMap<K, V>
for (Map.Entry<K,V> e : addMap.entrySet())
{
// Optimize in case the Entry is one of our own.
- if (e instanceof AbstractMap.BasicMapEntry)
+ if (e instanceof AbstractMap.SimpleEntry)
{
- AbstractMap.BasicMapEntry<? extends K, ? extends V> entry
- = (AbstractMap.BasicMapEntry<? extends K, ? extends V>) e;
+ AbstractMap.SimpleEntry<? extends K, ? extends V> entry
+ = (AbstractMap.SimpleEntry<? extends K, ? extends V>) e;
put(entry.key, entry.value);
}
else
diff --git a/java/util/Hashtable.java b/java/util/Hashtable.java
index 37ee03ccc..de3c4a944 100644
--- a/java/util/Hashtable.java
+++ b/java/util/Hashtable.java
@@ -175,7 +175,7 @@ public class Hashtable<K, V> extends Dictionary<K, V>
* `null' is not allowed for keys and values.
*/
private static final class HashEntry<K, V>
- extends AbstractMap.BasicMapEntry<K, V>
+ extends AbstractMap.SimpleEntry<K, V>
{
/** The next entry in the linked list. */
HashEntry<K, V> next;
@@ -512,10 +512,10 @@ public class Hashtable<K, V> extends Dictionary<K, V>
for (Map.Entry<K,V> e : addMap.entrySet())
{
// Optimize in case the Entry is one of our own.
- if (e instanceof AbstractMap.BasicMapEntry)
+ if (e instanceof AbstractMap.SimpleEntry)
{
- AbstractMap.BasicMapEntry<? extends K, ? extends V> entry
- = (AbstractMap.BasicMapEntry<? extends K, ? extends V>) e;
+ AbstractMap.SimpleEntry<? extends K, ? extends V> entry
+ = (AbstractMap.SimpleEntry<? extends K, ? extends V>) e;
put(entry.key, entry.value);
}
else
diff --git a/java/util/TreeMap.java b/java/util/TreeMap.java
index 46f405c59..d366f067e 100644
--- a/java/util/TreeMap.java
+++ b/java/util/TreeMap.java
@@ -162,7 +162,7 @@ public class TreeMap<K, V> extends AbstractMap<K, V>
*
* @author Eric Blake (ebb9@email.byu.edu)
*/
- private static final class Node<K, V> extends AbstractMap.BasicMapEntry<K, V>
+ private static final class Node<K, V> extends AbstractMap.SimpleEntry<K, V>
{
// All fields package visible for use by nested classes.
/** The color of this node. */
diff --git a/vm/reference/gnu/classpath/Unsafe.java b/vm/reference/gnu/classpath/Unsafe.java
new file mode 100644
index 000000000..3494f5fc6
--- /dev/null
+++ b/vm/reference/gnu/classpath/Unsafe.java
@@ -0,0 +1,328 @@
+/* Unsafe.java - Unsafe operations needed for concurrency
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.classpath;
+
+import java.lang.reflect.Field;
+
+/**
+ * This class should provide access to low-level operations and its
+ * use should be limited to trusted code. Fields can be accessed using
+ * memory addresses, with undefined behaviour occurring if invalid memory
+ * addresses are given.
+ *
+ * @author Tom Tromey (tromey@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+public class Unsafe
+{
+ // Singleton class.
+ private static Unsafe unsafe = new Unsafe();
+
+ /**
+ * Private default constructor to prevent creation of an arbitrary
+ * number of instances.
+ */
+ private Unsafe()
+ {
+ }
+
+ /**
+ * Retrieve the singleton instance of <code>Unsafe</code>. The calling
+ * method should guard this instance from untrusted code, as it provides
+ * access to low-level operations such as direct memory access.
+ *
+ * @throws SecurityException if a security manager exists and prevents
+ * access to the system properties.
+ */
+ public static Unsafe getUnsafe()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPropertiesAccess();
+ return unsafe;
+ }
+
+ /**
+ * Returns the memory address offset of the given static field.
+ * The offset is merely used as a means to access a particular field
+ * in the other methods of this class. The value is unique to the given
+ * field and the same value should be returned on each subsequent call.
+ *
+ * @param field the field whose offset should be returned.
+ * @return the offset of the given field.
+ */
+ public native long objectFieldOffset(Field field);
+
+ /**
+ * Compares the value of the integer field at the specified offset
+ * in the supplied object with the given expected value, and updates
+ * it if they match. The operation of this method should be atomic,
+ * thus providing an uninterruptible way of updating an integer field.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the integer field within <code>obj</code>.
+ * @param expect the expected value of the field.
+ * @param update the new value of the field if it equals <code>expect</code>.
+ * @return true if the field was changed.
+ */
+ public native boolean compareAndSwapInt(Object obj, long offset,
+ int expect, int update);
+
+ /**
+ * Compares the value of the long field at the specified offset
+ * in the supplied object with the given expected value, and updates
+ * it if they match. The operation of this method should be atomic,
+ * thus providing an uninterruptible way of updating a long field.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @param expect the expected value of the field.
+ * @param update the new value of the field if it equals <code>expect</code>.
+ * @return true if the field was changed.
+ */
+ public native boolean compareAndSwapLong(Object obj, long offset,
+ long expect, long update);
+
+ /**
+ * Compares the value of the object field at the specified offset
+ * in the supplied object with the given expected value, and updates
+ * it if they match. The operation of this method should be atomic,
+ * thus providing an uninterruptible way of updating an object field.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the object field within <code>obj</code>.
+ * @param expect the expected value of the field.
+ * @param update the new value of the field if it equals <code>expect</code>.
+ * @return true if the field was changed.
+ */
+ public native boolean compareAndSwapObject(Object obj, long offset,
+ Object expect, Object update);
+
+ /**
+ * Sets the value of the integer field at the specified offset in the
+ * supplied object to the given value. This is an ordered or lazy
+ * version of <code>putIntVolatile(Object,long,int)</code>, which
+ * doesn't guarantee the immediate visibility of the change to other
+ * threads. It is only really useful where the integer field is
+ * <code>volatile</code>, and is thus expected to change unexpectedly.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the integer field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putIntVolatile(Object,long,int)
+ */
+ public native void putOrderedInt(Object obj, long offset, int value);
+
+ /**
+ * Sets the value of the long field at the specified offset in the
+ * supplied object to the given value. This is an ordered or lazy
+ * version of <code>putLongVolatile(Object,long,long)</code>, which
+ * doesn't guarantee the immediate visibility of the change to other
+ * threads. It is only really useful where the long field is
+ * <code>volatile</code>, and is thus expected to change unexpectedly.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putLongVolatile(Object,long,long)
+ */
+ public native void putOrderedLong(Object obj, long offset, long value);
+
+ /**
+ * Sets the value of the object field at the specified offset in the
+ * supplied object to the given value. This is an ordered or lazy
+ * version of <code>putObjectVolatile(Object,long,Object)</code>, which
+ * doesn't guarantee the immediate visibility of the change to other
+ * threads. It is only really useful where the object field is
+ * <code>volatile</code>, and is thus expected to change unexpectedly.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the object field within <code>obj</code>.
+ * @param value the new value of the field.
+ */
+ public native void putOrderedObject(Object obj, long offset, Object value);
+
+ /**
+ * Sets the value of the integer field at the specified offset in the
+ * supplied object to the given value, with volatile store semantics.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the integer field within <code>obj</code>.
+ * @param value the new value of the field.
+ */
+ public native void putIntVolatile(Object obj, long offset, int value);
+
+ /**
+ * Retrieves the value of the integer field at the specified offset in the
+ * supplied object with volatile load semantics.
+ *
+ * @param obj the object containing the field to read.
+ * @param offset the offset of the integer field within <code>obj</code>.
+ */
+ public native int getIntVolatile(Object obj, long offset);
+
+ /**
+ * Sets the value of the long field at the specified offset in the
+ * supplied object to the given value, with volatile store semantics.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putLong(Object,long,long)
+ */
+ public native void putLongVolatile(Object obj, long offset, long value);
+
+ /**
+ * Sets the value of the long field at the specified offset in the
+ * supplied object to the given value.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putLongVolatile(Object,long,long)
+ */
+ public native void putLong(Object obj, long offset, long value);
+
+ /**
+ * Retrieves the value of the long field at the specified offset in the
+ * supplied object with volatile load semantics.
+ *
+ * @param obj the object containing the field to read.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @see #getLong(Object,long)
+ */
+ public native long getLongVolatile(Object obj, long offset);
+
+ /**
+ * Retrieves the value of the long field at the specified offset in the
+ * supplied object.
+ *
+ * @param obj the object containing the field to read.
+ * @param offset the offset of the long field within <code>obj</code>.
+ * @see #getLongVolatile(Object,long)
+ */
+ public native long getLong(Object obj, long offset);
+
+ /**
+ * Sets the value of the object field at the specified offset in the
+ * supplied object to the given value, with volatile store semantics.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the object field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putObject(Object,long,Object)
+ */
+ public native void putObjectVolatile(Object obj, long offset, Object value);
+
+ /**
+ * Sets the value of the object field at the specified offset in the
+ * supplied object to the given value.
+ *
+ * @param obj the object containing the field to modify.
+ * @param offset the offset of the object field within <code>obj</code>.
+ * @param value the new value of the field.
+ * @see #putObjectVolatile(Object,long,Object)
+ */
+ public native void putObject(Object obj, long offset, Object value);
+
+ /**
+ * Retrieves the value of the object field at the specified offset in the
+ * supplied object with volatile load semantics.
+ *
+ * @param obj the object containing the field to read.
+ * @param offset the offset of the object field within <code>obj</code>.
+ */
+ public native Object getObjectVolatile(Object obj, long offset);
+
+ /**
+ * Returns the offset of the first element for a given array class.
+ * To access elements of the array class, this value may be used along
+ * with that returned by
+ * <a href="#arrayIndexScale"><code>arrayIndexScale</code></a>,
+ * if non-zero.
+ *
+ * @param arrayClass the class for which the first element's address should
+ * be obtained.
+ * @return the offset of the first element of the array class.
+ * @see arrayIndexScale(Class)
+ */
+ public native int arrayBaseOffset(Class arrayClass);
+
+ /**
+ * Returns the scale factor used for addressing elements of the supplied
+ * array class. Where a suitable scale factor can not be returned (e.g.
+ * for primitive types), zero should be returned. The returned value
+ * can be used with
+ * <a href="#arrayBaseOffset"><code>arrayBaseOffset</code></a>
+ * to access elements of the class.
+ *
+ * @param arrayClass the class whose scale factor should be returned.
+ * @return the scale factor, or zero if not supported for this array class.
+ */
+ public native int arrayIndexScale(Class arrayClass);
+
+ /**
+ * Releases the block on a thread created by
+ * <a href="#park"><code>park</code></a>. This method can also be used
+ * to terminate a blockage caused by a prior call to <code>park</code>.
+ * This operation is unsafe, as the thread must be guaranteed to be
+ * live. This is true of Java, but not native code.
+ *
+ * @param thread the thread to unblock.
+ */
+ public native void unpark(Thread thread);
+
+ /**
+ * Blocks the thread until a matching
+ * <a href="#unpark"><code>unpark</code></a> occurs, the thread is
+ * interrupted or the optional timeout expires. If an <code>unpark</code>
+ * call has already occurred, this also counts. A timeout value of zero
+ * is defined as no timeout. When <code>isAbsolute</code> is
+ * <code>true</code>, the timeout is in milliseconds relative to the
+ * epoch. Otherwise, the value is the number of nanoseconds which must
+ * occur before timeout. This call may also return spuriously (i.e.
+ * for no apparent reason).
+ *
+ * @param isAbsolute true if the timeout is specified in milliseconds from
+ * the epoch.
+ * @param time either the number of nanoseconds to wait, or a time in
+ * milliseconds from the epoch to wait for.
+ */
+ public native void park(boolean isAbsolute, long time);
+
+}
diff --git a/vm/reference/java/lang/VMSystem.java b/vm/reference/java/lang/VMSystem.java
index 6002ab132..5ed2228c8 100644
--- a/vm/reference/java/lang/VMSystem.java
+++ b/vm/reference/java/lang/VMSystem.java
@@ -137,6 +137,11 @@ final class VMSystem
*/
public static native long currentTimeMillis();
+ public static long nanoTime()
+ {
+ return currentTimeMillis() * 1000;
+ }
+
/**
* Returns a list of 'name=value' pairs representing the current environment
* variables.