diff options
author | John Keiser <shalom@gnu.org> | 1998-10-17 20:33:59 +0000 |
---|---|---|
committer | John Keiser <shalom@gnu.org> | 1998-10-17 20:33:59 +0000 |
commit | df30658b9df671a678a9a0d76d1078b7d72a110c (patch) | |
tree | 9bed325d5607d19ab504cceb3b029983139eb636 | |
parent | 8cf3c66259e5edd396ae48a98bc29ae71f4d864f (diff) | |
download | classpath-df30658b9df671a678a9a0d76d1078b7d72a110c.tar.gz |
Moved some files that are VM-specific over from the main tree.
Fixed a few typos too.
-rw-r--r-- | vm/reference/gnu/vm/stack/StackFrame.java | 62 | ||||
-rw-r--r-- | vm/reference/gnu/vm/stack/StackTrace.java | 65 | ||||
-rw-r--r-- | vm/reference/java/lang/Thread.java | 556 | ||||
-rw-r--r-- | vm/reference/java/lang/VMSecurityManager.java | 2 | ||||
-rw-r--r-- | vm/reference/java/lang/reflect/Constructor.java | 199 | ||||
-rw-r--r-- | vm/reference/java/lang/reflect/Field.java | 356 | ||||
-rw-r--r-- | vm/reference/java/lang/reflect/Method.java | 222 |
7 files changed, 1461 insertions, 1 deletions
diff --git a/vm/reference/gnu/vm/stack/StackFrame.java b/vm/reference/gnu/vm/stack/StackFrame.java new file mode 100644 index 000000000..9339a63ba --- /dev/null +++ b/vm/reference/gnu/vm/stack/StackFrame.java @@ -0,0 +1,62 @@ +/* + * gnu.java.lang.StackFrame: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.vm.stack; + +import java.lang.reflect.*; + +/** + ** StackFrame represents a single frame of the Java + ** execution stack, frozen in time. + ** + ** @author John Keiser + ** @version 1.1.0, Aug 11 1998 + **/ +public class StackFrame { + StackFrame caller; + Object obj; + Method method; + int lineNum; + String filename; + + private StackFrame(Object obj, Method method, int lineNum, String filename) { + this.caller = caller; + this.obj = obj; + this.method = method; + this.lineNum = lineNum; + this.filename = filename; + } + + public String getSourceFilename() { + return filename; + } + + public Object getCalledObject() { + return obj; + } + + public Method getCalledMethod() { + return method; + } + + public int getSourceLineNumber() { + return lineNum; + } +} diff --git a/vm/reference/gnu/vm/stack/StackTrace.java b/vm/reference/gnu/vm/stack/StackTrace.java new file mode 100644 index 000000000..2bab71363 --- /dev/null +++ b/vm/reference/gnu/vm/stack/StackTrace.java @@ -0,0 +1,65 @@ +/* + * gnu.java.lang.ExecutionStack: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package gnu.vm.stack; + +import java.lang.reflect.*; + +/** + ** StackTrace represents a Java system execution + ** stack and allows you to get information off of it. + ** + ** @author John Keiser + ** @version 1.1.0, Aug 11 1998 + **/ +public class StackTrace { + StackFrame[] frames; + int len; + + public static StackTrace copyCurrentStackTrace() { + return new StackTrace(new StackFrame[0]); + } + + public static StackTrace copyStackTrace(Thread t) { + return new StackTrace(new StackFrame[0]); + } + + StackTrace(StackFrame[] frames) { + this.frames = frames; + len = frames.length; + } + + public synchronized StackFrame pop() { + if(len == 0) + throw new ArrayIndexOutOfBoundsException("stack trace empty."); + len--; + return frames[len]; + } + + public synchronized StackFrame frameAt(int i) { + if(i > len) + throw new ArrayIndexOutOfBoundsException(i + " > " + len); + return frames[i]; + } + + public synchronized int numFrames() { + return len; + } +} diff --git a/vm/reference/java/lang/Thread.java b/vm/reference/java/lang/Thread.java new file mode 100644 index 000000000..7cbef65d4 --- /dev/null +++ b/vm/reference/java/lang/Thread.java @@ -0,0 +1,556 @@ +/*
+ * java.lang.Thread: part of the Java Class Libraries project.
+ * Copyright (C) 1998 John Keiser
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+package java.lang;
+
+/**
+ ** Thread represents a single thread of execution in the VM.
+ ** When an application VM starts up, it creates a new Thread
+ ** which calls the main() method of a particular class. There
+ ** may be other Threads running, such as the garbage collection
+ ** thread.<P>
+ **
+ ** Threads have names to identify them. These names are not
+ ** necessarily unique.<P>
+ **
+ ** Every Thread has a priority, as well, which tells the VM
+ ** which Threads get more running time.<P>
+ **
+ ** There are two methods of creating a Thread: you may
+ ** subclass Thread and implement the <CODE>run()</CODE> method, at which
+ ** point you may start the Thread by calling its <CODE>start()</CODE>
+ ** method, or you may implement <CODE>Runnable</CODE> in the class you
+ ** want to use and then call new <CODE>Thread(your_obj).start()</CODE>.
+ **
+ ** @specnote it is unclear at what point a Thread should be added to a
+ ** ThreadGroup, and at what point it should be removed.
+ ** Should it be inserted when it starts, or when it is
+ ** created? Should it be removed when it is suspended or
+ ** interrupted? The only thing that is clear is that the
+ ** Thread should be removed when it is stopped.
+ ** @author John Keiser
+ ** @version 1.1.0, Aug 6 1998
+ ** @since JDK1.0
+ **/
+
+public class Thread {
+ static final byte INITIALIZED = 0;
+ static final byte RUNNING = 1;
+ static final byte SUSPENDED = 2;
+ static final byte INTERRUPTED = 3;
+ static final byte STOPPED = 4;
+ static final byte SLEEPING= 5;
+ static final byte WAITING_FOR_LOCK = 6;
+ static final byte STOPPED_BEFORE_START = 7;
+
+ ThreadGroup group;
+ Runnable toRun;
+ String name;
+ boolean daemon;
+ byte state = INITIALIZED;
+
+ /** The maximum priority for a Thread.
+ ** @XXX find out the value for this.
+ **/
+ public static final int MAX_PRIORITY;
+
+ /** The priority a Thread gets by default.
+ ** @XXX find out the value for this.
+ **/
+ public static final int NORM_PRIORITY;
+
+ /** The minimum priority for a Thread.
+ ** @XXX find out the value for this.
+ **/
+ public static final int MIN_PRIORITY;
+
+ static int numThreadsCreated = 0;
+
+ int priority;
+
+ /** Allocate a new Thread object, with the same ThreadGroup
+ ** as the calling thread, with an automatic name, and using
+ ** Thread's <CODE>run()</CODE> method to execute.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.<P>
+ **
+ ** This method is identical to calling
+ ** <CODE>Thread(null,null,<I>fake name</I>)</CODE>, where the
+ ** fake name in this case is automatically generated with the
+ ** name "Thread-" + <I>arbitrary integer</I>.
+ **/
+ public Thread() {
+ this(null,null,null);
+ }
+
+ /** Allocate a new Thread object, with the same ThreadGroup
+ ** as the calling thread, with an automatic name, and using
+ ** the specified Runnable object's <CODE>run()</CODE> method
+ ** to execute. If the Runnable object is null, Thread's
+ ** <CODE>run()</CODE> will be called instead.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.<P>
+ **
+ ** This method is identical to calling
+ ** <CODE>Thread(null,target,<I>fake name</I>)</CODE>, where the
+ ** fake name in this case is automatically generated with the
+ ** name "Thread-" + <I>arbitrary integer</I>.
+ **
+ ** @param toRun the Runnable object to execute.
+ **/
+ public Thread(Runnable toRun) {
+ this(null,toRun);
+ }
+
+ /** Allocate a new Thread object, with the specified ThreadGroup,
+ ** with an automatic name, and using the specified Runnable
+ ** object's <CODE>run()</CODE> method to execute. If the
+ ** Runnable object is null, Thread's <CPDE>run()</CODE> will be
+ ** called instead. If the ThreadGroup object is null, the Thread
+ ** will get the same ThreadGroup as the creating Thread.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.<P>
+ **
+ ** This method is identical to calling
+ ** <CODE>Thread(null,target,<I>fake name</I>)</CODE>, where the
+ ** fake name in this case is automatically generated with the
+ ** name "Thread-" + <I>arbitrary integer</I>.
+ **
+ ** @param group the group to put the Thread into.
+ ** @param target the Runnable object to execute.
+ **
+ ** @exception SecurityException if this thread cannot access the
+ ** specified ThreadGroup.
+ **/
+ public Thread(ThreadGroup group, Runnable toRun) {
+ this(group,toRun,"Thread-" + (++numThreadsCreated));
+ }
+
+ /** Allocate a new Thread object, with the same ThreadGroup
+ ** as the calling thread, with the specified name, and using
+ ** Thread's <CODE>run()</CODE> method to execute.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.<P>
+ **
+ ** This method is identical to calling
+ ** <CODE>Thread(null,null,name)</CODE>.
+ **
+ ** @param name the name for the Thread.
+ **/
+ public Thread(String name) {
+ this(null,null,name);
+ }
+
+ /** Allocate a new Thread object, with the same ThreadGroup
+ ** as the calling thread, with the specified name, and using
+ ** the specified Runnable object's <CODE>run()</CODE> method
+ ** to execute. If the Runnable object is null, Thread's
+ ** <CPDE>run()</CODE> will be called instead.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.<P>
+ **
+ ** This method is identical to calling
+ ** <CODE>Thread(null,target,name)</CODE>.
+ **
+ ** @param toRun the Runnable object to execute.
+ ** @param name the name for the Thread.
+ **/
+ public Thread(Runnable toRun, String name) {
+ this(null,toRun,name);
+ }
+
+ /** Allocate a new Thread object, with the specified ThreadGroup,
+ ** with the specified name, and using the specified Runnable
+ ** object's <CODE>run()</CODE> method to execute. If the
+ ** Runnable object is null, Thread's <CPDE>run()</CODE> will be
+ ** called instead. If the ThreadGroup object is null, the Thread
+ ** will get the same ThreadGroup as the creating Thread.<P>
+ **
+ ** The new Thread will inherit its creator's priority and
+ ** will be marked as a daemon if its creator is a daemon.
+ **
+ ** @param group the group to put the Thread into.
+ ** @param target the Runnable object to execute.
+ ** @param name the name for the Thread.
+ **
+ ** @exception SecurityException if this thread cannot access the
+ ** specified ThreadGroup.
+ **/
+ public Thread(ThreadGroup group, Runnable toRun, String name) {
+ if(group != null) {
+ this.group = group;
+ group.checkAccess();
+ } else {
+ this.group = currentThread().getThreadGroup();
+ }
+ this.toRun = toRun;
+ this.name = name;
+ priority = currentThread().getPriority();
+ daemon = currentThread().isDaemon();
+ nativeInit();
+
+ this.group.addThread(this);
+ }
+
+ /** Get the currently executing Thread.
+ ** @return the currently executing Thread.
+ **/
+ public static native Thread currentThread();
+
+ /** Suspend the current Thread's execution for the specified
+ ** amount of time. The Thread will not lose any locks it has
+ ** during this time.
+ **
+ ** @param ms the number of milliseconds to sleep.
+ ** @exception InterruptedException if the Thread is interrupted
+ ** by another Thread.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public static void sleep(long ms) throws InterruptedException {
+ sleep(ms,0);
+ }
+
+ /** Suspend the current Thread's execution for the specified
+ ** amount of time. The Thread will not lose any locks it has
+ ** during this time.
+ **
+ ** @param ms the number of milliseconds to sleep.
+ ** @param ns the number of extra nanoseconds to sleep (0-999999).
+ ** @exception InterruptedException if the Thread is interrupted
+ ** by another Thread.
+ **/
+ public static void sleep(long ms, int ns) throws InterruptedException {
+ synchronized(currentThread()) {
+ if(currentThread().state != RUNNING && currentThread().state != INTERRUPTED) {
+ return;
+ }
+ try {
+ currentThread().state = SLEEPING;
+ currentThread().nativeSleep(ms,ns);
+ } catch(InterruptedException e) {
+ currentThread().state = INTERRUPTED;
+ throw e;
+ }
+ currentThread().state = RUNNING;
+ }
+ }
+
+ /** Start this Thread, calling the run() method of the Runnable
+ ** this Thread was created with or else the run() method of the
+ ** Thread itself.
+ **/
+ public synchronized void start() {
+ if(state == INITIALIZED) {
+ nativeStart();
+ state = RUNNING;
+ }
+ }
+
+ /** The method of Thread that will be run if there is no Runnable
+ ** object associated with the Thread.<P>
+ **
+ ** Thread's implementation does nothing at all.
+ **/
+ public void run() {
+ }
+
+ /** Cause this Thread to stop abnormally and throw a ThreadDeath
+ ** exception.<P>
+ **
+ ** If you stop a Thread that has not yet started, it will stop
+ ** immediately when it is actually started.<P>
+ **
+ ** @exception SecurityException if you cannot modify this Thread.
+ ** @XXX it doesn't yet implement that second requirement.
+ **/
+ public final void stop() {
+ stop(new ThreadDeath());
+ }
+
+ /** Cause this Thread to stop abnormally and throw the specified
+ ** exception.<P>
+ **
+ ** If you stop a Thread that has not yet started, it will stop
+ ** immediately when it is actually started.<P>
+ **
+ ** @param t the Throwable to throw when the Thread dies.
+ ** @exception SecurityException if you cannot modify this Thread.
+ ** @XXX it doesn't yet implement that second requirement.
+ **/
+ public final synchronized void stop(Throwable t) {
+ checkAccess();
+ group.removeThread(this);
+ nativeStop(t);
+ state = STOPPED;
+ }
+
+ /** Interrupt this Thread.
+ ** It is not clear whether locks this Thread has should be released.
+ ** This operation will only take place if the Thread is suspended
+ ** or is sleeping.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public synchronized void interrupt() {
+ checkAccess();
+ if(state == SUSPENDED || state == SLEEPING) {
+ nativeInterrupt();
+ state = INTERRUPTED;
+ }
+ }
+
+ /** Destroy this thread. Don't even bother to clean up locks.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public synchronized void destroy() {
+ checkAccess();
+ group.removeThread(this);
+ state = STOPPED;
+ nativeDestroy();
+ }
+
+ /** Suspend this Thread. It will not come back, ever, unless
+ ** it is resumed. It is not clear whether locks should be
+ ** released until resumption, but it is likely.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public final synchronized void suspend() {
+ checkAccess();
+ if(state == RUNNING || state == INTERRUPTED) {
+ nativeSuspend();
+ state = SUSPENDED;
+ }
+ }
+
+ /** Resume this Thread. If the thread is not suspended, this
+ ** method does nothing.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public final synchronized void resume() {
+ checkAccess();
+ if(state != SUSPENDED) {
+ nativeResume();
+ state = RUNNING;
+ }
+ }
+
+ /** Wait forever for the Thread in question to die.
+ ** @exception InterruptedException if this Thread is interrupted
+ ** while waiting.
+ **/
+ public final void join() throws InterruptedException {
+ join(0,0);
+ }
+
+ /** Wait the specified amount of time for the Thread in question to
+ ** die.
+ ** @param ms the number of milliseconds to wait, or 0 for forever.
+ ** @exception InterruptedException if this Thread is interrupted
+ ** while waiting.
+ **/
+ public final void join(long ms) throws InterruptedException {
+ join(ms,0);
+ }
+
+ /** Wait the specified amount of time for the Thread in question to
+ ** die.
+ ** @param ms the number of milliseconds to wait, or 0 for forever.
+ ** @param ns the number of nanoseconds (0-999999) to wait, or 0 for
+ ** forever.
+ ** @exception InterruptedException if this Thread is interrupted
+ ** while waiting.
+ ** @XXX a ThreadListener would be nice. Then perhaps this could be
+ ** made efficient.
+ **/
+ public final void join(long ms, int ns) throws InterruptedException {
+ if(ms == 0 && ns == 0) {
+ while(!isAlive())
+ currentThread().sleep(1);
+ } else {
+ for(long i=0;i<ms;i++) {
+ if(isAlive())
+ return;
+ currentThread().sleep(1);
+ }
+ currentThread().sleep(0,ns);
+ }
+ }
+
+ /** Print a stack trace of the current thread to stderr using
+ ** the same format as Throwable's printStackTrace() method.
+ **/
+ public static void dumpStack() {
+ new Throwable().printStackTrace();
+ }
+
+
+ /** Set this Thread's priority.
+ ** @param priority the new priority for this Thread.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public final void setPriority(int priority) {
+ checkAccess();
+ if(priority < MIN_PRIORITY
+ || priority > MAX_PRIORITY
+ || priority > group.getMaxPriority())
+ throw new IllegalArgumentException("Invalid thread priority value " + priority + ".");
+ this.priority = priority;
+ }
+
+ /** Get this Thread's priority.
+ ** @return the Thread's priority.
+ **/
+ public final int getPriority() {
+ return priority;
+ }
+
+ /** Set this Thread's name.
+ ** @param name the new name for this Thread.
+ ** @exception SecurityException if you cannot modify this Thread.
+ **/
+ public final void setName(String name) {
+ checkAccess();
+ this.name = name;
+ }
+
+ /** Get this Thread's name.
+ ** @return this Thread's name.
+ **/
+ public final String getName() {
+ return name;
+ }
+
+ /** Get the ThreadGroup this Thread belongs to.
+ ** @return this Thread's ThreadGroup.
+ **/
+ public final ThreadGroup getThreadGroup() {
+ return group;
+ }
+
+ /** Set the daemon status of this Thread. If this is a
+ ** daemon Thread, then the VM may exit even if it is still
+ ** running. This may only be called when the Thread is not
+ ** running.
+ **
+ ** @specnote It is possible that this should only be called
+ ** if the Thread has not been started. This
+ ** interpretation was easier to implement, though,
+ ** so it's the one I chose :)
+ ** @param daemon whether this should be a daemon thread or not.
+ ** @exception SecurityException if you cannot modify this Thread.
+ ** @exception IllegalThreadStateException if the Thread is active.
+ **/
+ public final void setDaemon(boolean daemon) {
+ this.daemon = daemon;
+ }
+
+ /** Tell whether this is a daemon Thread or not.
+ ** @return whether this is a daemon Thread or not.
+ **/
+ public final boolean isDaemon() {
+ return daemon;
+ }
+
+
+ /** Get the number of active threads in the current Thread's
+ ** ThreadGroup. This implementation calls
+ ** <CODE>currentThread().getThreadGroup().activeCount()</CODE>.
+ ** @return the number of active threads in the current Thread's
+ ** ThreadGroup.
+ **/
+ public static int activeCount() {
+ return currentThread().group.activeCount();
+ }
+
+ /** Copy every active thread in the current Thread's ThreadGroup
+ ** into the array. This implementation calls
+ ** <CODE>getThreadGroup().enumerate(array)</CODE>
+ ** @param array the array to place the Threads into.
+ ** @return the number of Threads placed into the array.
+ **/
+ public static int enumerate(Thread[] array) {
+ return currentThread().group.enumerate(array);
+ }
+
+ /** Count the number of stack frames in this Thread. The Thread
+ ** in question must be suspended when this occurs.
+ **
+ ** @return the number of stack frames in this Thread.
+ ** @exception IllegalThreadStateException if this Thread is
+ ** not suspended.
+ **/
+ public native int countStackFrames();
+
+
+ /** Determine whether the current Thread has been interrupted.
+ ** @return whether the current Thread has been interrupted.
+ **/
+ public static boolean interrupted() {
+ return currentThread().isInterrupted();
+ }
+
+ /** Determine whether this Thread has been interrupted.
+ ** @return whether this Thread has been interrupted.
+ **/
+ public boolean isInterrupted() {
+ return state == INTERRUPTED;
+ }
+
+ /** Determine whether this Thread is alive.
+ ** @return whether this Thread is alive.
+ **/
+ public final boolean isAlive() {
+ return state != STOPPED && state != INITIALIZED;
+ }
+
+
+ /** Check whether the current Thread is allowed to
+ ** modify this Thread.
+ ** @exception SecurityException if the current Thread cannot
+ ** modify this Thread.
+ **/
+ public void checkAccess() {
+ SecurityManager sm = System.getSecurityManager();
+ if(sm != null) {
+ sm.checkAccess(this);
+ }
+ }
+
+ /** Return a human-readable String representing this Thread.
+ ** @return a human-readable String representing this Thread.
+ ** @XXX determine the exact format of this String.
+ **/
+ public String toString() {
+ return "";
+ }
+
+ final native void nativeInit();
+ final native void nativeStop(Throwable t);
+ final native void nativeStart();
+ final native void nativeInterrupt();
+ final native void nativeDestroy();
+ final native void nativeSuspend();
+ final native void nativeResume();
+ final native void nativeSleep(long ms, int ns) throws InterruptedException;
+}
diff --git a/vm/reference/java/lang/VMSecurityManager.java b/vm/reference/java/lang/VMSecurityManager.java index 938784a13..74ab587b8 100644 --- a/vm/reference/java/lang/VMSecurityManager.java +++ b/vm/reference/java/lang/VMSecurityManager.java @@ -48,5 +48,5 @@ class VMSecurityManager { ** top of the stack.
** @return the current ClassLoader.
**/
- static native Class currentClassLoader();
+ static native ClassLoader currentClassLoader();
}
diff --git a/vm/reference/java/lang/reflect/Constructor.java b/vm/reference/java/lang/reflect/Constructor.java new file mode 100644 index 000000000..e9d0720d2 --- /dev/null +++ b/vm/reference/java/lang/reflect/Constructor.java @@ -0,0 +1,199 @@ +/* + * java.lang.reflect.Constructor: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package java.lang.reflect; + +/** + ** Constructor represents a constructor of a class. + ** It will allow you to create a new instance of the class or get generic + ** information about the constructor.<P> + ** + ** <B>Note:</B> This class returns and accepts types as Classes, even + ** primitive types; there are Class types defined that represent each + ** different primitive type. They are <code>java.lang.Boolean.TYPE, + ** java.lang.Byte.TYPE, </code>etc. These are not to be confused with + ** the classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., + ** which are real classes.<P> + ** + ** <STRONG>Serialization:</STROMG>Note that this is not a serializable + ** class. It is entirely feasible to make it serializable, but this + ** is on Sun, not me.<P> + ** + ** <STRONG>Access and Security:</STRONG> Once this Constructor is created + ** by java.lang.Class (which does its own security check), any object may + ** query it for information like parameter types, exception types, etc. + ** However, the Constructor may only be invoked using standard Java + ** language access controls. The JLS says that reflective access to all + ** private, public and protected reflective members is granted to any + ** class which can be linked against the reflected member. Link-level + ** enforcement is the enforcement of public, private, protected and + ** default access rules, based on the caller's relationship to the class + ** (same package, subclass, or unrelated). Thus, if you couldn't + ** normally invoke this constructor from the calling class, you can't do + ** it using a Constructor object either.<P> + ** + ** The relevant section of the VM spec on link-security is <A + ** HREF='http://java.sun.com/docs/books/vmspec/html/Concepts.doc.html#22574'>2.16.3</A>, under Resolution. + ** A summary of the appropriate rules follows.<P> + ** + ** <STRONG>Summary of access rules</STRONG><BR> + ** Two checks are done, and they are the same checks--on both the member's class and the member itself: + ** <UL> + ** <LI>If the caller is the same class as the member's class, then it can access the member no matter + ** what.</LI> + ** <LI>If the caller is in the same package as the member's class, then the member's class and the member + ** itself must both be public, protected or default access.</LI> + ** <LI>If the caller is a subclass of the member's class, then the member's class and the member itself must + ** both be public or protected access.</LI> + ** <LI>If the caller is unrelated member's class, then the member's class and the member must + ** be public access.</LI> + ** </UL> + ** <P> + ** + ** As far as I can tell from the fairly confusing <A + ** HREF='http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html'>Inner + ** Classes Specification</A>, there should be no change to these rules from the addition of inner + ** classes in 1.1.<P> + ** + ** <STRONG>Version note:</STRONG> In 1.2, the security checks can be disabled in the AccessibleObject + ** interface. But this ain't 1.2. :)<P> + ** + ** <STRONG>BUGS:</STRONG> The maximum size of a signature right now is 4096 characters because I'm using + ** a static buffer when I calculate them. While fine for most purposes, it is for pathological cases that + ** specs are built. I'm not sure how I'll handle this yet. + ** + ** @author John Keiser + ** @version 1.1.0, 31 May 1998 + ** @see Member + ** @see java.lang.Class#getConstructor(Object[]) + ** @see java.lang.Class#getDeclaredConstructor(Object[]) + ** @see java.lang.Class#getConstructors() + ** @see java.lang.Class#getDeclaredConstructors() + **/ + +public final class Constructor implements Member { + private Class declaringClass; + private int slot; + + /* This class is uninstantiable except from native code. */ + private Constructor(Class declaringClass,int slot) { + this.declaringClass = declaringClass; + this.slot = slot; + } + + /** Gets the class that declared this constructor. + ** @specnote It is unclear whether this returns the class that + ** actually syntactically declared the member, or the + ** class where the Constructor object was gotten from. + ** @return the class that declared this member. + **/ + public Class getDeclaringClass() { + return declaringClass; + } + + /** Gets the modifiers this constructor uses. Use the <code>Modifier</code> + ** class to interpret the values. + ** A Constructor may only have the modifiers public, private and protected. + ** @see Modifier + ** @return an integer representing the modifiers to this Member. + **/ + public native int getModifiers(); + + /** Gets the name of this constructor (the non-qualified name of the class it was declared in). + ** @return the name of this constructor. + **/ + public String getName() { + return getDeclaringClass().getName(); + } + + /** Get the parameter list for this constructor. + ** @return a list of classes representing the names of the constructor's parameters. + **/ + public native Class[] getParameterTypes(); + + /** Get the exception types this constructor says it throws. + ** @return a list of classes representing the exception types. + **/ + public native Class[] getExceptionTypes(); + + /** Compare two objects to see if they are semantically equivalent. + ** Two Constructors are semantically equivalent if they have the same declaring class and the + ** same parameter list. <B>Though I really don't see how two different Constructor objects with + ** identical parameters could be created.</B> + ** @param o the object to compare to. + ** @return <code>true<code> if they are equal; <code>false</code> if not. + **/ + public boolean equals(Object o) { + return this == o; + } + + /** Get the hash code for the Constructor. + ** Constructor hash code is the hash code of the declaring class's name. + ** @return the hash code for the object. + **/ + public int hashCode() { + return getDeclaringClass().getName().hashCode(); + } + + /** Get a String representation of the Constructor. + ** A Constructor's String representation is <modifiers> <classname>(<paramtypes>). + ** Example: <code>public java.lang.Thread(java.lang.Runnable,int)</code> + ** @return the String representation of the Constructor. + **/ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(Modifier.toString(getModifiers())); + sb.append(' '); + sb.append(getDeclaringClass().getName()); + sb.append('('); + Class[] c = getParameterTypes(); + if(c.length > 0) { + sb.append(c[0].getName()); + for(int i = 1; i < c.length; i++) { + sb.append(','); + sb.append(c[i].getName()); + } + } + return sb.toString(); + } + + /** Create a new instance of the object the constructor can construct. + ** The constructor will permit widening argument conversions, but not narrowing conversions. + ** @param args the arguments to the constructor. + ** @return the newly created object. + ** @exception InstantiationException if the class is abstract. <B>Never mind that there + ** should be no constructors in an abstract class.</B> + ** @exception IllegalAccessException if the constructor could not normally be called + ** by the Java code (i.e. it is not public). + ** @exception IllegalArgumentException if the number of arguments is incorrect, or if the + ** arguments cannot be converted to the actual argument + ** types, even with a widening conversion. + ** @exception InvocationTargetException if the constructor throws an exception. + **/ + public Object newInstance(Object args[]) + throws InstantiationException, + IllegalAccessException, + IllegalArgumentException, + InvocationTargetException { + return constructNative(args, declaringClass, slot); + } + + private native Object constructNative(Object[] args, Class declaringClass, int slot); +} diff --git a/vm/reference/java/lang/reflect/Field.java b/vm/reference/java/lang/reflect/Field.java new file mode 100644 index 000000000..c17a83563 --- /dev/null +++ b/vm/reference/java/lang/reflect/Field.java @@ -0,0 +1,356 @@ +/* + * java.lang.reflect.Field: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package java.lang.reflect; + +/** + ** The Field class represents a member variable of a class. + ** It allows you to read and manipulate that variable.<P> + ** + ** <B>Note:</B> This class returns and accepts types as Classes, even primitive types; there are Class + ** types defined that represent each different primitive type. They are <code>java.lang.Boolean.TYPE, + ** java.lang.Byte.TYPE, </code>etc. These are not to be confused with the classes + ** <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are real classes.<P> + ** + ** Also note that this is not a serializable class. It is entirely feasible to make it serializable + ** using the Externalizable interface, but this is on Sun, not me. + ** + ** @author John Keiser + ** @version 1.1.0, 31 May 1998 + ** @see Member + ** @see java.lang.Class#getField(String) + ** @see java.lang.Class#getDeclaredField(String) + ** @see java.lang.Class#getFields() + ** @see java.lang.Class#getDeclaredFields() + **/ +public final class Field implements Member { + private Class declaringClass; + private String name; + private int slot; + + /* This class is uninstantiable except natively. */ + private Field(Class declaringClass, String name, int slot) { + this.declaringClass = declaringClass; + this.name = name; + this.slot = slot; + } + + /** Gets the class that declared this field. + ** <B>It is unclear whether this returns the class that actually syntactically declared + ** the member, or the class where the Field object was gotten from.</B> + ** @return the class that declared this member. + **/ + public Class getDeclaringClass() { + return declaringClass; + } + + /** Gets the modifiers this field uses. Use the <code>Modifier</code> + ** class to interpret the values. A field can only have the following + ** modifiers: public, private, protected, static, final, transient, and volatile. + ** @see Modifier + ** @return an integer representing the modifiers to this Member. + **/ + public native int getModifiers(); + + /** Gets the name of this field. + ** @return the name of this field. + **/ + public String getName() { + return name; + } + + /** Gets the type of this field. + ** @return the type of this field. + **/ + public native Class getType(); + + /** Compare two objects to see if they are semantically equivalent. + ** Two Fields are semantically equivalent if they have the same declaring class and the + ** same name. + ** @param o the object to compare to. + ** @return <code>true<code> if they are equal; <code>false</code> if not. + **/ + public boolean equals(Object o) { + return this == o; + } + + /** Get the hash code for the Field. + ** The Field hash code is the hash code of its name XOR'd with the hash code of its class name. + ** @return the hash code for the object. + **/ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** Get a String representation of the Field. + ** A Field's String representation is <modifiers> <type> <class>.<fieldname>. + ** Example: <code>public transient boolean gnu.parse.Parser.parseComplete</code> + ** @return the String representation of the Constructor. + **/ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(Modifier.toString(getModifiers())); + sb.append(' '); + sb.append(getType().getName()); + sb.append(' '); + sb.append(getDeclaringClass().getName()); + sb.append('.'); + sb.append(getName()); + return sb.toString(); + } + + /** Get the value of this Field. If it is primitive, it will be wrapped in the + ** appropriate wrapper type (boolean = java.lang.Boolean) + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this field is not a field of <code>o</code>. + **/ + public Object get(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this boolean Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a boolean field of <code>o</code>. + **/ + public native boolean getBoolean(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this byte Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a byte field of <code>o</code>. + **/ + public native byte getByte(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as a short. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to a short. + **/ + public native short getShort(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as a char. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to a char. + **/ + public native char getChar(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as an int. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to an int. + **/ + public native int getInt(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as a long. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to a long. + **/ + public native long getLong(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as a float. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to a float. + **/ + public float getFloat(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Get the value of this Field as a double. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to get the value of this Field from. + ** @return the value of the Field. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this is not a field of <code>o</code> or is + ** a field of <code>o</code> but cannot be converted + ** via a widening conversion to a double. + **/ + public double getDouble(Object o) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this Field. If it is a primitive field, the value passed must be wrapped in + ** the appropriate wrapped type (boolean = java.lang.Boolean) + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if <code>value</code> cannot be converted by a + ** widening conversion to the underlying type of + ** the Field. + **/ + public void set(Object o, Object value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this boolean Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this field is not a primitive boolean field. + **/ + public void setBoolean(Object o, boolean value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this byte Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if a byte cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setByte(Object o, byte value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this short Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if a byte cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setShort(Object o, short value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this char Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if a char cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setChar(Object o, char value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this int Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if an int cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setInt(Object o, int value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this long Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if a long cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setLong(Object o, long value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this float Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to. + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if a float cannot be converted via a widening + ** conversion to the type of this field. + **/ + public void setFloat(Object o, float value) + throws IllegalAccessException, + IllegalArgumentException; + + /** Set this double Field. + ** If the field is static, <code>o</code> will be ignored. + ** @param o the object to set this Field on. + ** @param value the value to set this Field to + ** @exception IllegalAccessException if you could not normally access this field + ** (i.e. it is not public). + ** @exception IllegalArgumentException if this field is not a primitive double field. + **/ + public void setDouble(Object o, double value) + throws IllegalAccessException, + IllegalArgumentException; +} diff --git a/vm/reference/java/lang/reflect/Method.java b/vm/reference/java/lang/reflect/Method.java new file mode 100644 index 000000000..5f00bb307 --- /dev/null +++ b/vm/reference/java/lang/reflect/Method.java @@ -0,0 +1,222 @@ +/* + * java.lang.reflect.Method: part of the Java Class Libraries project. + * Copyright (C) 1998 John Keiser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +package java.lang.reflect; + +/** + ** Method is a class which represents a method. + ** You may get information about it and make calls on it.<P> + ** + ** <STRONG>Note:</STRONG> This class returns and accepts types as Classes, even primitive types; there are Class + ** types defined that represent each different primitive type. They are <code>java.lang.Boolean.TYPE, + ** java.lang.Byte.TYPE, </code>etc. These are not to be confused with the classes + ** <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are real classes.<P> + ** + ** <STRONG>Serialization:</STROMG>Note that this is not a serializable class. It is entirely feasible to make it + ** serializable, but this is on Sun, not me.<P> + ** + ** <STRONG>Access and Security:</STRONG> Once this Method is created by java.lang.Class (which does its own + ** security check), any object may query it for information like parameter types, exception types, etc. + ** However, the Method may only be invoked using standard Java language access controls. The JLS says that + ** reflective access to all private, public and protected reflective members is granted to any class which + ** can be linked against the reflected member. Link-level enforcement is the enforcement of public, private, + ** protected and default access rules, based on the caller's relationship to the class (same package, + ** subclass, or unrelated). Thus, if you couldn't normally invoke this method from the calling class, you + ** can't do it using a Method object either.<P> + ** + ** The relevant section of the VM spec on link-security is <A + ** HREF='http://java.sun.com/docs/books/vmspec/html/Concepts.doc.html#22574'>2.16.3</A>, under Resolution. + ** A summary of the appropriate rules follows.<P> + ** + ** <STRONG>Summary of access rules</STRONG><BR> + ** Two checks are done, and they are the same checks--on both the member's class and the member itself: + ** <UL> + ** <LI>If the caller is the same class as the member's class, then it can access the member no matter + ** what.</LI> + ** <LI>If the caller is in the same package as the member's class, then the member's class and the member + ** itself must both be public, protected or default access.</LI> + ** <LI>If the caller is a subclass of the member's class, then the member's class and the member itself must + ** both be public or protected access.</LI> + ** <LI>If the caller is in the same package as the member's class, then the member's class and the member must + ** be public access.</LI> + ** </UL> + ** <P> + ** + ** As far as I can tell from the fairly confusing <A + ** HREF='http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html'>Inner + ** Classes Specification</A>, there should be no change to these rules from the addition of inner + ** classes in 1.1.<P> + ** + ** <STRONG>Version note:</STRONG> In 1.2, the security checks can be disabled in the AccessibleObject + ** interface. But this ain't 1.2. :)<P> + ** + ** <STRONG>BUGS:</STRONG> The maximum size of a signature right now is 4096 characters because I'm using + ** a static buffer when I calculate them. While fine for most purposes, it is for pathological cases that + ** specs are built. I'm not sure how I'll handle this yet. + ** + ** @author John Keiser + ** @version 1.1.0, 31 May 1998 + ** @see Member + ** @see java.lang.Class#getMethod(String,Object[]) + ** @see java.lang.Class#getDeclaredMethod(String,Object[]) + ** @see java.lang.Class#getMethods() + ** @see java.lang.Class#getDeclaredMethods() + **/ + +public final class Method implements Member { + Class declaringClass; + String name; + int slot; + + /* This class is uninstantiable. */ + private Method(Class declaringClass, String name, int slot) { + this.declaringClass = declaringClass; + this.name = name; + this.slot = slot; + } + + /** Gets the class that declared this method. + ** <STRONG>It is unclear whether this returns the class that actually syntactically declared + ** the member, or the class where the Method object was gotten from.</STRONG> + ** @return the class that declared this member. + **/ + public Class getDeclaringClass() { + return declaringClass; + } + + /** Gets the modifiers this method uses. Use the <code>Modifier</code> + ** class to interpret the values. + ** A Method may only have the modifiers public, private, protected, abstract, + ** static, final, synchronized, and native. + ** @see Modifier + ** @return an integer representing the modifiers to this Member. + **/ + public native int getModifiers(); + + /** Gets the name of this method. + ** @return the name of this method. + **/ + public String getName() { + return name; + } + + /** Gets the return type of this method. + ** @return the type of this method. + **/ + public native Class getReturnType(); + + /** Get the parameter list for this method. + ** @return a list of classes representing the names of the method's parameters. + **/ + public native Class[] getParameterTypes(); + + /** Get the exception types this method says it throws. + ** @return a list of classes representing the exception types. + **/ + public native Class[] getExceptionTypes(); + + /** Compare two objects to see if they are semantically equivalent. + ** Two Methods are semantically equivalent if they have the same declaring class, name, + ** and parameter list. <STRONG>Though I really don't see how two different Method objects + ** with identical parameters could be created.</STRONG> + ** @param o the object to compare to. + ** @return <code>true<code> if they are equal; <code>false</code> if not. + **/ + public boolean equals(Object o) { + return this == o; + } + + /** Get the hash code for the Method. + ** Constructor hash code is the hash code of the declaring class's name XOR'd with the method name. + ** @return the hash code for the object. + **/ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** Get a String representation of the Constructor. + ** A Constructor's String representation is <modifiers> <returntype> <methodname>(<paramtypes>). + ** Example: <code>public static int run(java.lang.Runnable,int)</code> + ** @return the String representation of the Constructor. + **/ + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(Modifier.toString(getModifiers())); + sb.append(' '); + sb.append(getReturnType()); + sb.append(' '); + sb.append(getDeclaringClass().getName()); + sb.append('.'); + sb.append(getName()); + sb.append('('); + Class[] c = getParameterTypes(); + if(c.length > 0) { + sb.append(c[0].getName()); + for(int i = 1; i < c.length; i++) { + sb.append(','); + sb.append(c[i].getName()); + } + } + sb.append(')'); + return sb.toString(); + } + + + /** Invoke the method.<P> + ** The method will permit widening argument conversions, but not narrowing conversions.<P> + ** For static methods, declaringClass is used for the Method lookup, not the class of the Object + ** being invoked on.<P> + ** For instance methods, the method in the class of the Object itself is invoked.<P> + ** + ** The permissions and workings of this method are the same as if you had invoked the method in Java + ** using ((<declaringClass>)o).<methodName>(<args>). If your object had enough permissions to do + ** that, then this call will succeed.<P> + ** + ** <STRONG>Robustness Note:</STRONG> if the method returns an Object of the wrong type somehow, then + ** that will not be checked by invoke(). Shouldn't happen anyway, but this information is included + ** for completeness. + ** + ** @param o the object to invoke the method on. + ** @param args the arguments to the method. + ** @return the return value of the method, wrapped in the appropriate wrapper if it is primitive. + ** @exception IllegalAccessException if the method could not normally be called + ** by the Java code (see note at beginning of class + ** for more information). + ** @exception IllegalArgumentException if the number of arguments is incorrect; if the + ** arguments cannot be converted to the actual argument + ** types, even with a widening conversion; for instance + ** methods, if the Object invoked on is not of appropriate + ** type. + ** @exception InvocationTargetException if the method throws an exception. + **/ + public Object invoke(Object o, Object[] args) + throws IllegalAccessException, + IllegalArgumentException, + InvocationTargetException { + return invokeNative(o, args, declaringClass, slot); + } + + /* + * NATIVE HELPERS + */ + + private native Object invokeNative(Object o, Object[] args, + Class declaringClass, int slot); +} |