1999-04-07 22:42:40 +08:00
|
|
|
// Class.java - Representation of a Java class.
|
|
|
|
|
2002-06-12 01:33:22 +08:00
|
|
|
/* Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation
|
1999-04-07 22:42:40 +08:00
|
|
|
|
|
|
|
This file is part of libgcj.
|
|
|
|
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
package java.lang;
|
|
|
|
import java.io.Serializable;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.lang.reflect.*;
|
2001-04-25 23:45:15 +08:00
|
|
|
import java.security.*;
|
1999-04-07 22:42:40 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Tom Tromey <tromey@cygnus.com>
|
|
|
|
* @date October 1, 1998
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
|
|
|
|
* "The Java Language Specification", ISBN 0-201-63451-1
|
|
|
|
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
|
|
|
|
* plus gcj compiler sources (to determine object layout)
|
|
|
|
* Status: Sufficient for our purposes, but some methods missing
|
|
|
|
* and some not implemented.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public final class Class implements Serializable
|
|
|
|
{
|
|
|
|
public static native Class forName (String className)
|
|
|
|
throws ClassNotFoundException;
|
2001-04-25 23:45:15 +08:00
|
|
|
/** @since 1.2 */
|
|
|
|
public static native Class forName (String className, boolean initialize,
|
|
|
|
ClassLoader loader)
|
2000-11-26 11:58:56 +08:00
|
|
|
throws ClassNotFoundException;
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Class[] getClasses ();
|
|
|
|
public native ClassLoader getClassLoader ();
|
|
|
|
public native Class getComponentType ();
|
|
|
|
|
|
|
|
public native Constructor getConstructor (Class[] parameterTypes)
|
|
|
|
throws NoSuchMethodException, SecurityException;
|
|
|
|
|
2000-01-04 16:46:52 +08:00
|
|
|
// This is used to implement getConstructors and
|
|
|
|
// getDeclaredConstructors.
|
|
|
|
private native Constructor[] _getConstructors (boolean declared)
|
|
|
|
throws SecurityException;
|
|
|
|
|
|
|
|
public Constructor[] getConstructors () throws SecurityException
|
|
|
|
{
|
|
|
|
return _getConstructors (false);
|
|
|
|
}
|
1999-04-07 22:42:40 +08:00
|
|
|
|
|
|
|
public native Constructor getDeclaredConstructor (Class[] parameterTypes)
|
|
|
|
throws NoSuchMethodException, SecurityException;
|
2000-01-04 16:46:52 +08:00
|
|
|
|
|
|
|
public native Class[] getDeclaredClasses () throws SecurityException;
|
|
|
|
|
|
|
|
public Constructor[] getDeclaredConstructors () throws SecurityException
|
|
|
|
{
|
|
|
|
return _getConstructors (true);
|
|
|
|
}
|
|
|
|
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Field getDeclaredField (String fieldName)
|
|
|
|
throws NoSuchFieldException, SecurityException;
|
|
|
|
public native Field[] getDeclaredFields () throws SecurityException;
|
2002-09-04 05:33:46 +08:00
|
|
|
|
|
|
|
private native Method _getDeclaredMethod (String methodName,
|
|
|
|
Class[] parameterTypes);
|
|
|
|
|
|
|
|
public Method getDeclaredMethod (String methodName, Class[] parameterTypes)
|
|
|
|
throws NoSuchMethodException, SecurityException
|
|
|
|
{
|
|
|
|
SecurityManager sm = System.getSecurityManager();
|
|
|
|
if (sm != null)
|
|
|
|
{
|
|
|
|
sm.checkMemberAccess(this, Member.DECLARED);
|
|
|
|
Package p = getPackage();
|
|
|
|
if (p != null)
|
|
|
|
sm.checkPackageAccess(p.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
|
|
|
|
throw new NoSuchMethodException(methodName);
|
|
|
|
|
|
|
|
Method m = _getDeclaredMethod(methodName, parameterTypes);
|
|
|
|
if (m == null)
|
|
|
|
throw new NoSuchMethodException (methodName);
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Method[] getDeclaredMethods () throws SecurityException;
|
|
|
|
|
|
|
|
// This is marked as unimplemented in the JCL book.
|
|
|
|
public native Class getDeclaringClass ();
|
|
|
|
|
|
|
|
private native Field getField (String fieldName, int hash)
|
|
|
|
throws NoSuchFieldException, SecurityException;
|
|
|
|
|
|
|
|
public Field getField (String fieldName)
|
|
|
|
throws NoSuchFieldException, SecurityException
|
|
|
|
{
|
|
|
|
SecurityManager s = System.getSecurityManager();
|
|
|
|
if (s != null)
|
|
|
|
s.checkMemberAccess (this, java.lang.reflect.Member.DECLARED);
|
|
|
|
Field fld = getField(fieldName, fieldName.hashCode());
|
|
|
|
if (fld == null)
|
|
|
|
throw new NoSuchFieldException(fieldName);
|
|
|
|
return fld;
|
|
|
|
}
|
2000-01-04 16:46:52 +08:00
|
|
|
|
|
|
|
private native Field[] _getFields (Field[] result, int offset);
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Field[] getFields () throws SecurityException;
|
|
|
|
|
2001-04-25 23:45:15 +08:00
|
|
|
/**
|
|
|
|
* Returns the <code>Package</code> in which this class is defined
|
|
|
|
* Returns null when this information is not available from the
|
|
|
|
* classloader of this class or when the classloader of this class
|
|
|
|
* is null.
|
|
|
|
*
|
|
|
|
* @since 1.2
|
|
|
|
*/
|
|
|
|
public Package getPackage()
|
|
|
|
{
|
|
|
|
ClassLoader cl = getClassLoader();
|
|
|
|
if (cl != null)
|
|
|
|
{
|
|
|
|
String name = getName();
|
|
|
|
String pkg = "";
|
|
|
|
int idx = name.lastIndexOf('.');
|
|
|
|
if (idx >= 0)
|
|
|
|
pkg = name.substring(0, idx);
|
|
|
|
return cl.getPackage(pkg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Class[] getInterfaces ();
|
|
|
|
|
2000-01-04 16:46:52 +08:00
|
|
|
private final native void getSignature (StringBuffer buffer);
|
2000-01-06 00:35:20 +08:00
|
|
|
private static final native String getSignature (Class[] parameterTypes,
|
|
|
|
boolean is_construtor);
|
2000-01-04 16:46:52 +08:00
|
|
|
|
2002-07-06 04:40:11 +08:00
|
|
|
public native Method _getMethod (String methodName, Class[] parameterTypes);
|
|
|
|
|
|
|
|
public Method getMethod (String methodName, Class[] parameterTypes)
|
|
|
|
throws NoSuchMethodException, SecurityException
|
|
|
|
{
|
|
|
|
SecurityManager sm = System.getSecurityManager();
|
|
|
|
if (sm != null)
|
|
|
|
{
|
|
|
|
sm.checkMemberAccess(this, Member.PUBLIC);
|
|
|
|
Package p = getPackage();
|
|
|
|
if (p != null)
|
|
|
|
sm.checkPackageAccess(p.getName());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ("<init>".equals(methodName) || "<clinit>".equals(methodName))
|
|
|
|
throw new NoSuchMethodException(methodName);
|
|
|
|
|
|
|
|
Method m = _getMethod(methodName, parameterTypes);
|
|
|
|
if (m == null)
|
|
|
|
throw new NoSuchMethodException (methodName);
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2000-01-06 06:22:10 +08:00
|
|
|
private native int _getMethods (Method[] result, int offset);
|
1999-04-07 22:42:40 +08:00
|
|
|
public native Method[] getMethods () throws SecurityException;
|
|
|
|
|
|
|
|
public native int getModifiers ();
|
|
|
|
public native String getName ();
|
|
|
|
|
1999-08-18 22:16:42 +08:00
|
|
|
public java.net.URL getResource (String resourceName)
|
|
|
|
{
|
|
|
|
String name = resourcePath (resourceName);
|
|
|
|
ClassLoader loader = getClassLoader ();
|
|
|
|
if (loader == null)
|
|
|
|
return ClassLoader.getSystemResource (name);
|
|
|
|
else
|
|
|
|
return loader.getResource (name);
|
|
|
|
}
|
1999-04-07 22:42:40 +08:00
|
|
|
|
1999-08-18 22:16:42 +08:00
|
|
|
public java.io.InputStream getResourceAsStream (String resourceName)
|
1999-04-07 22:42:40 +08:00
|
|
|
{
|
1999-08-18 22:16:42 +08:00
|
|
|
String name = resourcePath (resourceName);
|
|
|
|
ClassLoader loader = getClassLoader ();
|
|
|
|
if (loader == null)
|
|
|
|
return ClassLoader.getSystemResourceAsStream (name);
|
|
|
|
else
|
|
|
|
return loader.getResourceAsStream (name);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String resourcePath (String resourceName)
|
|
|
|
{
|
|
|
|
if (resourceName.startsWith ("/"))
|
|
|
|
return resourceName.substring (1);
|
|
|
|
|
|
|
|
Class c = this;
|
|
|
|
while (c.isArray ())
|
|
|
|
c = c.getComponentType ();
|
|
|
|
|
|
|
|
String packageName = c.getName ().replace ('.', '/');
|
|
|
|
int end = packageName.lastIndexOf ('/');
|
|
|
|
if (end == -1)
|
|
|
|
return resourceName;
|
|
|
|
else
|
|
|
|
return packageName.substring (0, end+1) + resourceName;
|
1999-04-07 22:42:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: implement. Requires java.security.
|
|
|
|
public Object[] getSigners ()
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public native Class getSuperclass ();
|
|
|
|
public native boolean isArray ();
|
|
|
|
public native boolean isAssignableFrom (Class cls);
|
|
|
|
public native boolean isInstance (Object obj);
|
|
|
|
public native boolean isInterface ();
|
|
|
|
public native boolean isPrimitive ();
|
|
|
|
public native Object newInstance ()
|
|
|
|
throws InstantiationException, IllegalAccessException;
|
|
|
|
|
2001-04-25 23:45:15 +08:00
|
|
|
// We need a native method to retrieve the protection domain, because we
|
|
|
|
// can't add fields to java.lang.Class that are accessible from Java.
|
|
|
|
private native ProtectionDomain getProtectionDomain0();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the protection domain of this class. If the classloader
|
|
|
|
* did not record the protection domain when creating this class
|
|
|
|
* the unknown protection domain is returned which has a <code>null</code>
|
|
|
|
* code source and all permissions.
|
|
|
|
*
|
|
|
|
* @exception SecurityException if a security manager exists and the caller
|
|
|
|
* does not have <code>RuntimePermission("getProtectionDomain")</code>.
|
|
|
|
*
|
|
|
|
* @since 1.2
|
|
|
|
*/
|
|
|
|
public ProtectionDomain getProtectionDomain()
|
|
|
|
{
|
|
|
|
SecurityManager sm = System.getSecurityManager();
|
|
|
|
if (sm != null)
|
|
|
|
sm.checkPermission(ClassLoader.protectionDomainPermission);
|
|
|
|
|
|
|
|
ProtectionDomain protectionDomain = getProtectionDomain0();
|
|
|
|
|
|
|
|
if (protectionDomain == null)
|
|
|
|
return ClassLoader.unknownProtectionDomain;
|
|
|
|
else
|
|
|
|
return protectionDomain;
|
|
|
|
}
|
|
|
|
|
1999-04-07 22:42:40 +08:00
|
|
|
public String toString ()
|
|
|
|
{
|
|
|
|
if (isPrimitive ())
|
|
|
|
return getName ();
|
|
|
|
return (isInterface () ? "interface " : "class ") + getName ();
|
|
|
|
}
|
|
|
|
|
2002-06-12 01:33:22 +08:00
|
|
|
/**
|
|
|
|
* Returns the desired assertion status of this class, if it were to be
|
|
|
|
* initialized at this moment. The class assertion status, if set, is
|
|
|
|
* returned; the backup is the default package status; then if there is
|
|
|
|
* a class loader, that default is returned; and finally the system default
|
|
|
|
* is returned. This method seldom needs calling in user code, but exists
|
|
|
|
* for compilers to implement the assert statement. Note that there is no
|
|
|
|
* guarantee that the result of this method matches the class's actual
|
|
|
|
* assertion status.
|
|
|
|
*
|
|
|
|
* @return the desired assertion status
|
|
|
|
* @see ClassLoader#setClassAssertionStatus(String, boolean)
|
|
|
|
* @see ClassLoader#setPackageAssertionStatus(String, boolean)
|
|
|
|
* @see ClassLoader#setDefaultAssertionStatus(boolean)
|
|
|
|
* @since 1.4
|
|
|
|
*/
|
|
|
|
public boolean desiredAssertionStatus()
|
|
|
|
{
|
|
|
|
ClassLoader c = getClassLoader();
|
|
|
|
Object status;
|
|
|
|
if (c == null)
|
|
|
|
return VMClassLoader.defaultAssertionStatus();
|
|
|
|
if (c.classAssertionStatus != null)
|
|
|
|
synchronized (c)
|
|
|
|
{
|
|
|
|
status = c.classAssertionStatus.get(getName());
|
|
|
|
if (status != null)
|
|
|
|
return status.equals(Boolean.TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status = ClassLoader.systemClassAssertionStatus.get(getName());
|
|
|
|
if (status != null)
|
|
|
|
return status.equals(Boolean.TRUE);
|
|
|
|
}
|
|
|
|
if (c.packageAssertionStatus != null)
|
|
|
|
synchronized (c)
|
|
|
|
{
|
|
|
|
String name = getPackagePortion(getName());
|
|
|
|
if ("".equals(name))
|
|
|
|
status = c.packageAssertionStatus.get(null);
|
|
|
|
else
|
|
|
|
do
|
|
|
|
{
|
|
|
|
status = c.packageAssertionStatus.get(name);
|
|
|
|
name = getPackagePortion(name);
|
|
|
|
}
|
|
|
|
while (! "".equals(name) && status == null);
|
|
|
|
if (status != null)
|
|
|
|
return status.equals(Boolean.TRUE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
String name = getPackagePortion(getName());
|
|
|
|
if ("".equals(name))
|
|
|
|
status = ClassLoader.systemPackageAssertionStatus.get(null);
|
|
|
|
else
|
|
|
|
do
|
|
|
|
{
|
|
|
|
status = ClassLoader.systemPackageAssertionStatus.get(name);
|
|
|
|
name = getPackagePortion(name);
|
|
|
|
}
|
|
|
|
while (! "".equals(name) && status == null);
|
|
|
|
if (status != null)
|
|
|
|
return status.equals(Boolean.TRUE);
|
|
|
|
}
|
|
|
|
return c.defaultAssertionStatus;
|
|
|
|
}
|
|
|
|
|
1999-04-07 22:42:40 +08:00
|
|
|
// Don't allow new classes to be made.
|
|
|
|
private Class ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do a security check.
|
|
|
|
private void checkMemberAccess (int flags)
|
|
|
|
{
|
|
|
|
SecurityManager sm = System.getSecurityManager();
|
|
|
|
if (sm != null)
|
|
|
|
sm.checkMemberAccess(this, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the class.
|
|
|
|
private native void initializeClass ();
|
[multiple changes]
1999-08-09 Anthony Green <green@cygnus.com>
* gij.cc: New file.
* include/config.h.in: Rebuilt.
* acconfig.h: Add INTERPRETER.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
* Makefile.am (libffi_files): Identify the libffi object files for
inclusion in libgcj.
(LIBFFIINCS): Define.
* interpret.cc (gnu::gcj::runtime::MethodInvocation::continue1):
Dummy definition for configurations without an interpreter.
* java/net/natPlainSocketImpl.cc (getOption): Disamiguate call to
java::lang::Boolean constructor.
* include/java-interp.h: Always include java-cpool.h.
* java/lang/natClassLoader.cc (getVMClassLoader0): Always return 0
when INTERPRETER not defined.
* java/lang/Class.h (finalize): Define.
* gnu/gcj/util/path/DirectoryPathEntry.java (getURL): Catch
IOException from File.getCanonicalPath.
(getStream): Likewise.
* NEWS: More news.
* THANKS: More thanks.
1999-08-09 Kresten Krab Thorup <krab@gnu.org>
* resolve.cc (get_ffi_type_from_signature): Generate uint16 for
jchar type.
(_Jv_PrepareClass): Allow non-abstract classes to
have abstract subclasses.
(_Jv_ResolvePoolEntry): Revert subclass check for protected
fields and methods.
* interpret.cc (continue1/perform_invoke): Don't sign extend
uint16 return val.
(continue1/lshl,lshr): Push long, not int.
(continue1/ulshr): Use UINT64, not long long.
* defineclass.cc (handleFieldsEnd): Handle case when all fields
are static.
* java/lang/natClass.cc (forName): Add call to _Jv_InitClass.
* java/lang/FirstThread.java (run): Add top-level exception
handler.
(run0): Renamed from run.
1999-08-08 Kresten Krab Thorup <krab@gnu.org>
* configure.in (--with-interpreter): Added.
* include/config.h.in (INTERPRETER): Added.
* java/lang/ClassLoader.java: File replaced.
* java/lang/VMClassLoader.java: New file.
* java/lang/natClassLoader.cc: New file.
* gnu/gcj/runtime/MethodInvocation.java: New file.
* gnu/gcj/util/path/SearchPath.java: New file.
* gnu/gcj/util/path/PathEntry.java: New file.
* gnu/gcj/util/path/DirectoryPathEntry.java: New file.
* gnu/gcj/util/path/ZipPathEntry.java: New file.
* gnu/gcj/util/path/URLPathEntry.java: New file.
* gnu/gcj/util/path/CacheEntry.java: New file.
* include/java-interp.h: New file.
* include/java-cpool.h: New file.
* include/java-insns.h: New file.
* defineclass.cc: New file.
* interpret.cc: New file.
* resolve.cc: New file.
* java/lang/natClass.cc (loaded_classes, _Jv_RegisterClass,
_Jv_RegisterClasses, _Jv_FindClassInCache, _Jv_FindClass,
_Jv_NewClass, _Jv_FindArrayClass): Moved to natClassLoader.cc.
(finalize): New.
(STATE_NOTHING, STATE_RESOLVED, STATE_IN_PROGRESS, STATE_DONE,
STATE_ERROR): Moved to java/lang/Class.h and renamed with JV_
prefix.
(initializeClass): Use new JV_ prefixed names. Also, call
ClassLoader::resolveClass instead of _Jv_ResolveClass.
* java/lang/Class.h (JV_STATE_PRELOADING, JV_STATE_LOADING,
JV_STATE_LOADED, JV_STATE_COMPILED, JV_STATE_PREPARED,
JV_STATE_LINKED): New.
(_Jv_WaitForState, _Jv_RegisterInitiatingLoader,
_Jv_UnregisterClass, _Jv_InternClassStrings): New friends.
(_Jv_IsInterpretedClass, _Jv_InitField, _Jv_LookupDeclaredMethod,
_Jv_DetermineVTableIndex, _Jv_ResolvePoolEntry, _Jv_PrepareClass,
_Jv_ClassReader, _Jv_InterpClass, _Jv_InterpMethod,
_Jv_InterpMethodInvocation): New friends for interpreter.
(finalize): New.
(CONSTANT_Class, CONSTANT_String, etc.): Moved to
include/java-cpool.h and renamed with JV_ prefix.
* include/jvm.h (_Jv_makeUtf8Const, _Jv_makeUtf8TypeConst): New
decls.
(_Jv_UnregisterClass): New decl.
* java/lang/natClassLoader.cc (_Jv_FindArrayClass): Added
class loader argument.
(_Jv_FindClass): Use class loader.
* prims.cc (_Jv_makeUtf8Const): New function.
(_Jv_NewObjectArray): Change use of _Jv_FindArrayClass.
(_Jv_NewPrimArray): Ditto.
(_Jv_FindClassFromSignature): Ditto.
* java/lang/reflect/natArray.cc (newInstance): Ditto.
* java/lang/reflect/natMethod.cc (getType): Ditto.
* include/java-field.h (_Jv_Field::isRef): Make robust for
non-resolved contexts.
* boehm.cc (_Jv_MarkObj): Mark interpreter-related fields.
Also, don't mark class->next field.
* java/lang/VirtualMachineError.java: Added FIXME note.
* configure.in (INTERPSPEC): New spec.
* libgcj.spec.in: Added INTERPSPEC.
* Makefile.am: Added gcjh friends for java/lang/VMClassLoader and
gnu/gcj/runtime/MethodInvocation.
(libgcj_la_SOURCES): Added resolve.cc defineclass.cc interpret.cc.
(ordinary_java_source_files): Added above mentioned java classes.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
From-SVN: r28597
1999-08-08 22:06:23 +08:00
|
|
|
|
|
|
|
// finalization
|
|
|
|
protected native void finalize ();
|
2002-06-12 01:33:22 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Strip the last portion of the name (after the last dot).
|
|
|
|
*
|
|
|
|
* @param name the name to get package of
|
|
|
|
* @return the package name, or "" if no package
|
|
|
|
*/
|
|
|
|
private static String getPackagePortion(String name)
|
|
|
|
{
|
|
|
|
int lastInd = name.lastIndexOf('.');
|
|
|
|
if (lastInd == -1)
|
|
|
|
return "";
|
|
|
|
return name.substring(0, lastInd);
|
|
|
|
}
|
1999-04-07 22:42:40 +08:00
|
|
|
}
|