diff options
author | Bryce McKinlay <bryce@gcc.gnu.org> | 2005-02-22 03:13:35 +0000 |
---|---|---|
committer | Bryce McKinlay <bryce@gcc.gnu.org> | 2005-02-22 03:13:35 +0000 |
commit | f4294557b7ebb12ab58c9b57e1309d5f2fcfb019 (patch) | |
tree | 3b41b785f371a92850d3442fff7b7deb7e7ec0c4 /libjava | |
parent | bb2e1640492f6b6989131cef45519dfd47a1acbb (diff) | |
download | gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.zip gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.tar.gz gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.tar.bz2 |
[multiple changes]
2005-02-21 Bryce McKinlay <mckinlay@redhat.com>
Merge serialization from GNU Classpath.
* gcj/method.h: Add missing #includes.
* java/io/ObjectInputStream.java (readClassDescriptor): Check for
primitive class IDs on the stream here...
(resolveClass): ...not here.
* java/io/ObjectStreamField.java: Use VMObjectStream class calls to set
fields.
* java/io/VMObjectStreamClass.java (setDoubleNative, setFloatNative,
setLongNative, setIntNative, setShortNative, setCharNative,
setByteNative, setBooleanNative, setObjectNative): New native methods.
* java/io/natVMObjectStreamClass.java (setDoubleNative, setFloatNative,
setLongNative, setIntNative, setShortNative, setCharNative,
setByteNative, setBooleanNative, setObjectNative): Implement them.
* java/io/natObjectInputStream.cc (allocateObject): Add new parameters
from Classpath's version. Use _Jv_FromReflectedConstructor(). Call
the constructor here.
(callConstructor): Removed.
(getCallersClassLoader): Removed.
* java/lang/reflect/Field.java (setByte, setShort, setInt, setLong,
setFloat, setDouble, setChar, setBoolean): Add 'checkFinal' parameter
to control whether setting final field values is permitted. Call
getAddr() with checkFinal parameter instead of setAddr().
* java/lang/reflect/natField.cc (getType): Lookup and resolve field
only if not done already.
(getAddr): Add checkFinal parameter. Do the final field check only if
checkFinal is set.
(setAddr): Removed.
2005-02-21 Mark Wielaard <mark@klomp.org>
# Fixes bug #11957
* java/io/ObjectInputStream.java (resolveClass): Don't check "void"
twice.
2005-02-21 Mark Wielaard <mark@klomp.org>
Fixes bug #11618.
* java/io/ObjectInputStream.java (readClassDescriptor): Handle classes
without a super class and us ObjectStreamClass.lookupForClassObject().
(resolveClass): Check for primitive types.
(lookupClass): Return null when argument is null.
2005-02-21 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java
(readObject): Fix to consume TC_ENDBLOCKDATA after readExternal.
2005-02-21 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectOutputStream.java
(writeObject, callWriteMethod): Replaced reflection with accessing
cached info in ObjectStreamClass.
(getMethod): Removed.
* java/io/ObjectStreamClass.java
(findMethod): Added check to make sure the method found has the
right modifiers.
(cacheMethods): Added writeReplace and writeObject methods.
(setFlags): Look at new writeObjectMethod field instead of doing
reflection again.
(writeReplaceMethod): New field.
(writeObjectMethod): New field.
2005-02-21 Guilhem Lavaux <guilhem@kaffe.org>
Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java
(newObject): Changed prototype. Get a constructor reflect object
directly.
(callConstructor): Removed.
(allocateObject): Changed prototype.
(readClassDescriptor): Build the constructor reflection directly.
(readObject): Invoke newObject using the new prototype.
* java/io/ObjectStreamClass.java
(firstNonSerializableParent): Removed.
(firstNonSerializableParentConstructor): Added.
From-SVN: r95378
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 79 | ||||
-rw-r--r-- | libjava/gcj/method.h | 2 | ||||
-rw-r--r-- | libjava/java/io/ObjectInputStream.java | 127 | ||||
-rw-r--r-- | libjava/java/io/ObjectOutputStream.java | 62 | ||||
-rw-r--r-- | libjava/java/io/ObjectStreamField.java | 81 | ||||
-rw-r--r-- | libjava/java/io/VMObjectStreamClass.java | 92 | ||||
-rw-r--r-- | libjava/java/io/natObjectInputStream.cc | 44 | ||||
-rw-r--r-- | libjava/java/io/natVMObjectStreamClass.cc | 64 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Field.java | 58 | ||||
-rw-r--r-- | libjava/java/lang/reflect/natField.cc | 94 |
10 files changed, 451 insertions, 252 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 99183ff..0d96227 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,82 @@ +2005-02-21 Bryce McKinlay <mckinlay@redhat.com> + + Merge serialization from GNU Classpath. + * gcj/method.h: Add missing #includes. + * java/io/ObjectInputStream.java (readClassDescriptor): Check for + primitive class IDs on the stream here... + (resolveClass): ...not here. + * java/io/ObjectStreamField.java: Use VMObjectStream class calls to set + fields. + * java/io/VMObjectStreamClass.java (setDoubleNative, setFloatNative, + setLongNative, setIntNative, setShortNative, setCharNative, + setByteNative, setBooleanNative, setObjectNative): New native methods. + * java/io/natVMObjectStreamClass.java (setDoubleNative, setFloatNative, + setLongNative, setIntNative, setShortNative, setCharNative, + setByteNative, setBooleanNative, setObjectNative): Implement them. + * java/io/natObjectInputStream.cc (allocateObject): Add new parameters + from Classpath's version. Use _Jv_FromReflectedConstructor(). Call + the constructor here. + (callConstructor): Removed. + (getCallersClassLoader): Removed. + * java/lang/reflect/Field.java (setByte, setShort, setInt, setLong, + setFloat, setDouble, setChar, setBoolean): Add 'checkFinal' parameter + to control whether setting final field values is permitted. Call + getAddr() with checkFinal parameter instead of setAddr(). + * java/lang/reflect/natField.cc (getType): Lookup and resolve field + only if not done already. + (getAddr): Add checkFinal parameter. Do the final field check only if + checkFinal is set. + (setAddr): Removed. + +2005-02-21 Mark Wielaard <mark@klomp.org> + + # Fixes bug #11957 + * java/io/ObjectInputStream.java (resolveClass): Don't check "void" + twice. + +2005-02-21 Mark Wielaard <mark@klomp.org> + + Fixes bug #11618. + * java/io/ObjectInputStream.java (readClassDescriptor): Handle classes + without a super class and us ObjectStreamClass.lookupForClassObject(). + (resolveClass): Check for primitive types. + (lookupClass): Return null when argument is null. + +2005-02-21 Jeroen Frijters <jeroen@frijters.net> + + * java/io/ObjectInputStream.java + (readObject): Fix to consume TC_ENDBLOCKDATA after readExternal. + +2005-02-21 Jeroen Frijters <jeroen@frijters.net> + + * java/io/ObjectOutputStream.java + (writeObject, callWriteMethod): Replaced reflection with accessing + cached info in ObjectStreamClass. + (getMethod): Removed. + * java/io/ObjectStreamClass.java + (findMethod): Added check to make sure the method found has the + right modifiers. + (cacheMethods): Added writeReplace and writeObject methods. + (setFlags): Look at new writeObjectMethod field instead of doing + reflection again. + (writeReplaceMethod): New field. + (writeObjectMethod): New field. + +2005-02-21 Guilhem Lavaux <guilhem@kaffe.org> + Jeroen Frijters <jeroen@frijters.net> + + * java/io/ObjectInputStream.java + (newObject): Changed prototype. Get a constructor reflect object + directly. + (callConstructor): Removed. + (allocateObject): Changed prototype. + (readClassDescriptor): Build the constructor reflection directly. + (readObject): Invoke newObject using the new prototype. + + * java/io/ObjectStreamClass.java + (firstNonSerializableParent): Removed. + (firstNonSerializableParentConstructor): Added. + 2005-02-21 Mark Wielaard <mark@klomp.org> * gnu/java/locale/LocaleInformation_en.java: Extend diff --git a/libjava/gcj/method.h b/libjava/gcj/method.h index d4246e4..f97f865 100644 --- a/libjava/gcj/method.h +++ b/libjava/gcj/method.h @@ -12,6 +12,8 @@ details. */ #define __GCJ_METHOD_H__ #include <java/lang/Class.h> +#include <java/lang/reflect/Constructor.h> +#include <java/lang/reflect/Method.h> extern inline jmethodID _Jv_FromReflectedMethod (java::lang::reflect::Method *method) diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java index 6f4faf8..2cfe4c9 100644 --- a/libjava/java/io/ObjectInputStream.java +++ b/libjava/java/io/ObjectInputStream.java @@ -43,6 +43,7 @@ import gnu.classpath.Configuration; import gnu.java.io.ObjectIdentityWrapper; import java.lang.reflect.Array; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -122,15 +123,6 @@ public class ObjectInputStream extends InputStream */ public final Object readObject() throws ClassNotFoundException, IOException { - if (callersClassLoader == null) - { - callersClassLoader = getCallersClassLoader (); - if (Configuration.DEBUG && dump) - { - dumpElementln ("CallersClassLoader = " + callersClassLoader); - } - } - if (this.useSubclassMethod) return readObjectOverride(); @@ -272,7 +264,7 @@ public class ObjectInputStream extends InputStream readArrayElements(array, componentType); if(dump) for (int i = 0, len = Array.getLength(array); i < len; i++) - dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); + dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); ret_val = processResolution(null, array, handle); break; } @@ -302,13 +294,18 @@ public class ObjectInputStream extends InputStream obj.readExternal(this); if (read_from_blocks) - setBlockDataMode(oldmode); + { + setBlockDataMode(oldmode); + if (!oldmode) + if (this.realInputStream.readByte() != TC_ENDBLOCKDATA) + throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method."); + } ret_val = processResolution(osc, obj, handle); break; } // end if (osc.realClassIsExternalizable) - Object obj = newObject(clazz, osc.firstNonSerializableParent); + Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor); int handle = assignNewHandle(obj); Object prevObject = this.currentObject; @@ -399,8 +396,6 @@ public class ObjectInputStream extends InputStream setBlockDataMode(old_mode); this.isDeserializing = was_deserializing; - - depth -= 2; depth -= 2; @@ -506,7 +501,8 @@ public class ObjectInputStream extends InputStream flags, fields); assignNewHandle(osc); - ClassLoader currentLoader = currentLoader(); + if (callersClassLoader == null) + callersClassLoader = currentLoader(); for (int i = 0; i < field_count; i++) { @@ -527,12 +523,40 @@ public class ObjectInputStream extends InputStream class_name = String.valueOf(type_code); fields[i] = - new ObjectStreamField(field_name, class_name, currentLoader); + new ObjectStreamField(field_name, class_name, callersClassLoader); } /* Now that fields have been read we may resolve the class * (and read annotation if needed). */ - Class clazz = resolveClass(osc); + Class clazz; + try + { + clazz = resolveClass(osc); + } + catch (ClassNotFoundException cnfe) + { + // Maybe it was an primitive class? + if (name.equals("void")) + clazz = Void.TYPE; + else if (name.equals("boolean")) + clazz = Boolean.TYPE; + else if (name.equals("byte")) + clazz = Byte.TYPE; + else if (name.equals("short")) + clazz = Short.TYPE; + else if (name.equals("char")) + clazz = Character.TYPE; + else if (name.equals("int")) + clazz = Integer.TYPE; + else if (name.equals("long")) + clazz = Long.TYPE; + else if (name.equals("float")) + clazz = Float.TYPE; + else if (name.equals("double")) + clazz = Double.TYPE; + else + throw cnfe; + } boolean oldmode = setBlockDataMode(true); osc.setClass(clazz, lookupClass(clazz.getSuperclass())); @@ -542,16 +566,45 @@ public class ObjectInputStream extends InputStream // find the first non-serializable, non-abstract // class in clazz's inheritance hierarchy Class first_nonserial = clazz.getSuperclass(); - while (Serializable.class.isAssignableFrom(first_nonserial) - || Modifier.isAbstract(first_nonserial.getModifiers())) + // Maybe it is a primitive class, those don't have a super class, + // or Object itself. Otherwise we can keep getting the superclass + // till we hit the Object class, or some other non-serializable class. + + if (first_nonserial == null) + first_nonserial = clazz; + else + while (Serializable.class.isAssignableFrom(first_nonserial) + || Modifier.isAbstract(first_nonserial.getModifiers())) first_nonserial = first_nonserial.getSuperclass(); - osc.firstNonSerializableParent = first_nonserial; + final Class local_constructor_class = first_nonserial; + + osc.firstNonSerializableParentConstructor = + (Constructor)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + try + { + Constructor c = local_constructor_class. + getDeclaredConstructor(new Class[0]); + if (Modifier.isPrivate(c.getModifiers())) + return null; + return c; + } + catch (NoSuchMethodException e) + { + // error will be reported later, in newObject() + return null; + } + } + }); + osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz); osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz); ObjectStreamField[] stream_fields = osc.fields; - ObjectStreamField[] real_fields = ObjectStreamClass.lookup(clazz).fields; + ObjectStreamField[] real_fields = ObjectStreamClass.lookupForClassObject(clazz).fields; ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)]; int stream_idx = 0; @@ -717,6 +770,15 @@ public class ObjectInputStream extends InputStream protected Class resolveClass(ObjectStreamClass osc) throws ClassNotFoundException, IOException { + if (callersClassLoader == null) + { + callersClassLoader = currentLoader (); + if (Configuration.DEBUG && dump) + { + dumpElementln ("CallersClassLoader = " + callersClassLoader); + } + } + return Class.forName(osc.getName(), true, callersClassLoader); } @@ -750,8 +812,10 @@ public class ObjectInputStream extends InputStream */ private ObjectStreamClass lookupClass(Class clazz) { - ObjectStreamClass oclazz; + if (clazz == null) + return null; + ObjectStreamClass oclazz; oclazz = (ObjectStreamClass)classLookupTable.get(clazz); if (oclazz == null) return ObjectStreamClass.lookup(clazz); @@ -1767,14 +1831,14 @@ public class ObjectInputStream extends InputStream // returns a new instance of REAL_CLASS that has been constructed // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS) - private Object newObject (Class real_class, Class constructor_class) - throws ClassNotFoundException + private Object newObject (Class real_class, Constructor constructor) + throws ClassNotFoundException, IOException { + if (constructor == null) + throw new InvalidClassException("Missing accessible no-arg base class constructor for " + real_class.getName()); try { - Object obj = allocateObject (real_class); - callConstructor (constructor_class, obj); - return obj; + return allocateObject(real_class, constructor.getDeclaringClass(), constructor); } catch (InstantiationException e) { @@ -1810,8 +1874,6 @@ public class ObjectInputStream extends InputStream * @return The current class loader in the calling stack. */ private static native ClassLoader currentClassLoader (SecurityManager sm); - - private native ClassLoader getCallersClassLoader(); private void callReadMethod (Method readObject, Class klass, Object obj) throws ClassNotFoundException, IOException @@ -1844,11 +1906,9 @@ public class ObjectInputStream extends InputStream prereadFields = null; } - private native Object allocateObject (Class clazz) + private native Object allocateObject(Class clazz, Class constr_clazz, Constructor constructor) throws InstantiationException; - private native void callConstructor (Class clazz, Object obj); - private static final int BUFFER_SIZE = 1024; private DataInputStream realInputStream; @@ -1870,9 +1930,8 @@ public class ObjectInputStream extends InputStream private Hashtable classLookupTable; private GetField prereadFields; - private static boolean dump = false && Configuration.DEBUG; - private ClassLoader callersClassLoader; + private static boolean dump; // The nesting depth for debugging output private int depth = 0; diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java index 3482225..55763ee 100644 --- a/libjava/java/io/ObjectOutputStream.java +++ b/libjava/java/io/ObjectOutputStream.java @@ -250,6 +250,11 @@ public class ObjectOutputStream extends OutputStream break; } + Class clazz = obj.getClass(); + ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz); + if (osc == null) + throw new NotSerializableException(clazz.getName()); + if ((replacementEnabled || obj instanceof Serializable) && ! replaceDone) { @@ -257,19 +262,11 @@ public class ObjectOutputStream extends OutputStream if (obj instanceof Serializable) { - Method m = null; try { - Class classArgs[] = {}; - m = getMethod(obj.getClass(), "writeReplace", - classArgs); - // m can't be null by definition since an - // exception would have been thrown so a check - // for null is not needed. - obj = m.invoke(obj, new Object[] {}); - } - catch (NoSuchMethodException ignore) - { + Method m = osc.writeReplaceMethod; + if (m != null) + obj = m.invoke(obj, new Object[0]); } catch (IllegalAccessException ignore) { @@ -294,11 +291,6 @@ public class ObjectOutputStream extends OutputStream break; } - Class clazz = obj.getClass(); - ObjectStreamClass osc = ObjectStreamClass.lookupForClassObject(clazz); - if (osc == null) - throw new NotSerializableException(clazz.getName()); - if (clazz.isArray ()) { realOutput.writeByte(TC_ARRAY); @@ -347,8 +339,8 @@ public class ObjectOutputStream extends OutputStream fieldsAlreadyWritten = false; if (currentObjectStreamClass.hasWriteMethod()) { - if (dump) - dumpElementln ("WRITE METHOD CALLED FOR: " + obj); + if (dump) + dumpElementln ("WRITE METHOD CALLED FOR: " + obj); setBlockDataMode(true); callWriteMethod(obj, currentObjectStreamClass); setBlockDataMode(false); @@ -358,10 +350,10 @@ public class ObjectOutputStream extends OutputStream } else { - if (dump) - dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); - writeFields(obj, currentObjectStreamClass); - } + if (dump) + dumpElementln ("WRITE FIELDS CALLED FOR: " + obj); + writeFields(obj, currentObjectStreamClass); + } } this.currentObject = prevObject; @@ -1261,18 +1253,11 @@ public class ObjectOutputStream extends OutputStream private void callWriteMethod(Object obj, ObjectStreamClass osc) throws IOException { - Class klass = osc.forClass(); currentPutField = null; try { - Class classArgs[] = {ObjectOutputStream.class}; - Method m = getMethod(klass, "writeObject", classArgs); - Object args[] = {this}; - m.invoke(obj, args); - } - catch (NoSuchMethodException nsme) - { - // Nothing. + Object args[] = {this}; + osc.writeObjectMethod.invoke(obj, args); } catch (InvocationTargetException x) { @@ -1285,7 +1270,8 @@ public class ObjectOutputStream extends OutputStream IOException ioe = new IOException("Exception thrown from writeObject() on " + - klass + ": " + exception.getClass().getName()); + osc.forClass().getName() + ": " + + exception.getClass().getName()); ioe.initCause(exception); throw ioe; } @@ -1293,7 +1279,8 @@ public class ObjectOutputStream extends OutputStream { IOException ioe = new IOException("Failure invoking writeObject() on " + - klass + ": " + x.getClass().getName()); + osc.forClass().getName() + ": " + + x.getClass().getName()); ioe.initCause(x); throw ioe; } @@ -1535,15 +1522,6 @@ public class ObjectOutputStream extends OutputStream } } - private Method getMethod (Class klass, String name, Class[] args) - throws java.lang.NoSuchMethodException - { - final Method m = klass.getDeclaredMethod(name, args); - setAccessible.setMember(m); - AccessController.doPrivileged(setAccessible); - return m; - } - private void dumpElementln (String msg) { for (int i = 0; i < depth; i++) diff --git a/libjava/java/io/ObjectStreamField.java b/libjava/java/io/ObjectStreamField.java index 93a121c..8c1a5db 100644 --- a/libjava/java/io/ObjectStreamField.java +++ b/libjava/java/io/ObjectStreamField.java @@ -367,109 +367,46 @@ public class ObjectStreamField implements Comparable final void setBooleanField(Object obj, boolean val) { - try - { - field.setBoolean(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setBooleanNative(field, obj, val); } final void setByteField(Object obj, byte val) { - try - { - field.setByte(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setByteNative(field, obj, val); } final void setCharField(Object obj, char val) { - try - { - field.setChar(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setCharNative(field, obj, val); } final void setShortField(Object obj, short val) { - try - { - field.setShort(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setShortNative(field, obj, val); } final void setIntField(Object obj, int val) { - try - { - field.setInt(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setIntNative(field, obj, val); } final void setLongField(Object obj, long val) { - try - { - field.setLong(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setLongNative(field, obj, val); } final void setFloatField(Object obj, float val) { - try - { - field.setFloat(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setFloatNative(field, obj, val); } final void setDoubleField(Object obj, double val) { - try - { - field.setDouble(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setDoubleNative(field, obj, val); } final void setObjectField(Object obj, Object val) { - try - { - field.set(obj, val); - } - catch(IllegalAccessException x) - { - throw new InternalError(x.getMessage()); - } + VMObjectStreamClass.setObjectNative(field, obj, val); } } diff --git a/libjava/java/io/VMObjectStreamClass.java b/libjava/java/io/VMObjectStreamClass.java index fd4023e..d21de72 100644 --- a/libjava/java/io/VMObjectStreamClass.java +++ b/libjava/java/io/VMObjectStreamClass.java @@ -38,7 +38,7 @@ exception statement from your version. */ package java.io; -import java.lang.reflect.Method; +import java.lang.reflect.Field; final class VMObjectStreamClass { @@ -47,4 +47,94 @@ final class VMObjectStreamClass * (a.k.a. <clinit>). */ static native boolean hasClassInitializer (Class clazz); + + /** + * Sets the value of the specified "double" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setDoubleNative(Field field, Object obj, double val); + + /** + * Sets the value of the specified "float" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setFloatNative(Field field, Object obj, float val); + + /** + * Sets the value of the specified "long" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setLongNative(Field field, Object obj, long val); + + /** + * Sets the value of the specified "int" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setIntNative(Field field, Object obj, int val); + + /** + * Sets the value of the specified "short" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setShortNative(Field field, Object obj, short val); + + /** + * Sets the value of the specified "char" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setCharNative(Field field, Object obj, char val); + + /** + * Sets the value of the specified "byte" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setByteNative(Field field, Object obj, byte val); + + /** + * Sets the value of the specified "boolean" field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setBooleanNative(Field field, Object obj, boolean val); + + /** + * Sets the value of the specified object field, allowing final values + * to be assigned. + * + * @param field Field to set the value. + * @param obj Instance which will have its field set. + * @param val Value to put in the field. + */ + static native void setObjectNative(Field field, Object obj, Object val); } diff --git a/libjava/java/io/natObjectInputStream.cc b/libjava/java/io/natObjectInputStream.cc index 9da4910..0e0d5a7 100644 --- a/libjava/java/io/natObjectInputStream.cc +++ b/libjava/java/io/natObjectInputStream.cc @@ -12,6 +12,7 @@ details. */ #include <gcj/cni.h> #include <jvm.h> +#include <gcj/method.h> #include <java/io/ObjectInputStream$GetField.h> #include <java/io/ObjectInputStream.h> @@ -21,6 +22,8 @@ details. */ #include <java/lang/reflect/Method.h> #include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/SecurityManager.h> +#include <java/lang/reflect/Constructor.h> +#include <java/lang/reflect/Method.h> #ifdef DEBUG #include <java/lang/System.h> @@ -28,7 +31,8 @@ details. */ #endif jobject -java::io::ObjectInputStream::allocateObject (jclass klass) +java::io::ObjectInputStream::allocateObject (jclass klass, jclass, + ::java::lang::reflect::Constructor *ctr) { jobject obj = NULL; using namespace java::lang::reflect; @@ -41,21 +45,15 @@ java::io::ObjectInputStream::allocateObject (jclass klass) else { obj = _Jv_AllocObject (klass); - } + } } catch (jthrowable t) { return NULL; } - return obj; -} - + jmethodID meth = _Jv_FromReflectedConstructor (ctr); -void -java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj) -{ - jstring init_name = JvNewStringLatin1 ("<init>"); // This is a bit inefficient, and a bit of a hack, since we don't // actually use the Method and since what is returned isn't // technically a Method. We can't use Method.invoke as it looks up @@ -63,36 +61,12 @@ java::io::ObjectInputStream::callConstructor (jclass klass, jobject obj) JArray<jclass> *arg_types = (JArray<jclass> *) JvNewObjectArray (0, &java::lang::Class::class$, NULL); - java::lang::reflect::Method *m = klass->getPrivateMethod (init_name, - arg_types); + // We lie about this being a constructor. If we put `true' here // then _Jv_CallAnyMethodA would try to allocate the object for us. - jmethodID meth = (jmethodID) ((char *) (klass->methods) - + m->offset); _Jv_CallAnyMethodA (obj, JvPrimClass (void), meth, false, arg_types, NULL); -} -java::lang::ClassLoader* -java::io::ObjectInputStream::getCallersClassLoader () -{ - java::lang::ClassLoader *loader = NULL; - gnu::gcj::runtime::StackTrace *t - = new gnu::gcj::runtime::StackTrace(4); - java::lang::Class *klass = NULL; - try - { - for (int i = 2; !klass; i++) - { - klass = t->classAt (i); - } - loader = klass->getClassLoaderInternal(); - } - catch (::java::lang::ArrayIndexOutOfBoundsException *e) - { - // FIXME: RuntimeError - } - - return loader; + return obj; } java::lang::ClassLoader* diff --git a/libjava/java/io/natVMObjectStreamClass.cc b/libjava/java/io/natVMObjectStreamClass.cc index b7a056c..847b540 100644 --- a/libjava/java/io/natVMObjectStreamClass.cc +++ b/libjava/java/io/natVMObjectStreamClass.cc @@ -13,11 +13,75 @@ details. */ #include <java/io/VMObjectStreamClass.h> #include <java/lang/Class.h> +#include <java/lang/reflect/Field.h> + +using namespace java::lang::reflect; jboolean java::io::VMObjectStreamClass::hasClassInitializer (jclass klass) { + if (klass->isPrimitive()) + return false; _Jv_Method *meth = _Jv_GetMethodLocal(klass, gcj::clinit_name, gcj::void_signature); return (meth != NULL); } + +void +java::io::VMObjectStreamClass::setDoubleNative (Field *f, jobject obj, + jdouble val) +{ + f->setDouble (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setFloatNative (Field *f, jobject obj, + jfloat val) +{ + f->setFloat (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setLongNative (Field *f, jobject obj, jlong val) +{ + f->setLong (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setIntNative (Field *f, jobject obj, jint val) +{ + f->setInt (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setShortNative (Field *f, jobject obj, + jshort val) +{ + f->setShort (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setCharNative (Field *f, jobject obj, jchar val) +{ + f->setChar (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setByteNative (Field *f, jobject obj, jbyte val) +{ + f->setByte (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setBooleanNative (Field *f, jobject obj, + jboolean val) +{ + f->setBoolean (NULL, obj, val, false); +} + +void +java::io::VMObjectStreamClass::setObjectNative (Field *f, jobject obj, + jobject val) +{ + f->set (NULL, obj, val, f->getType(), false); +} diff --git a/libjava/java/lang/reflect/Field.java b/libjava/java/lang/reflect/Field.java index b54a103..cb852cf 100644 --- a/libjava/java/lang/reflect/Field.java +++ b/libjava/java/lang/reflect/Field.java @@ -23,6 +23,9 @@ public final class Field extends AccessibleObject implements Member // Offset in bytes from the start of declaringClass's fields array. private int offset; + // The Class (or primitive TYPE) of this field. + private Class type; + // This is instantiated by Class sometimes, but it uses C++ and // avoids the Java protection check. Field () @@ -136,76 +139,79 @@ public final class Field extends AccessibleObject implements Member public void setByte (Object obj, byte b) throws IllegalArgumentException, IllegalAccessException { - setByte(null, obj, b); + setByte(null, obj, b, true); } public void setShort (Object obj, short s) throws IllegalArgumentException, IllegalAccessException { - setShort(null, obj, s); + setShort(null, obj, s, true); } public void setInt (Object obj, int i) throws IllegalArgumentException, IllegalAccessException { - setInt(null, obj, i); + setInt(null, obj, i, true); } public void setLong (Object obj, long l) throws IllegalArgumentException, IllegalAccessException { - setLong(null, obj, l); + setLong(null, obj, l, true); } public void setFloat (Object obj, float f) throws IllegalArgumentException, IllegalAccessException { - setFloat(null, obj, f); + setFloat(null, obj, f, true); } public void setDouble (Object obj, double d) throws IllegalArgumentException, IllegalAccessException { - setDouble(null, obj, d); + setDouble(null, obj, d, true); } public void setChar (Object obj, char c) throws IllegalArgumentException, IllegalAccessException { - setChar(null, obj, c); + setChar(null, obj, c, true); } public void setBoolean (Object obj, boolean b) throws IllegalArgumentException, IllegalAccessException { - setBoolean(null, obj, b); + setBoolean(null, obj, b, true); } - private native void setByte (Class caller, Object obj, byte b) + native void setByte (Class caller, Object obj, byte b, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setShort (Class caller, Object obj, short s) + native void setShort (Class caller, Object obj, short s, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setInt (Class caller, Object obj, int i) + native void setInt (Class caller, Object obj, int i, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setLong (Class caller, Object obj, long l) + native void setLong (Class caller, Object obj, long l, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setFloat (Class caller, Object obj, float f) + native void setFloat (Class caller, Object obj, float f, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setDouble (Class caller, Object obj, double d) + native void setDouble (Class caller, Object obj, double d, + boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setChar (Class caller, Object obj, char c) + native void setChar (Class caller, Object obj, char c, boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void setBoolean (Class caller, Object obj, boolean b) + native void setBoolean (Class caller, Object obj, boolean b, + boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; - private native void set (Class caller, Object obj, Object val, Class type) + native void set (Class caller, Object obj, Object val, Class type, + boolean checkFinal) throws IllegalArgumentException, IllegalAccessException; public void set (Object object, Object value) @@ -219,23 +225,23 @@ public final class Field extends AccessibleObject implements Member { Class type = getType(); if (! type.isPrimitive()) - set(caller, object, value, type); + set(caller, object, value, type, true); else if (value instanceof Byte) - setByte(caller, object, ((Byte) value).byteValue()); + setByte(caller, object, ((Byte) value).byteValue(), true); else if (value instanceof Short) - setShort (caller, object, ((Short) value).shortValue()); + setShort (caller, object, ((Short) value).shortValue(), true); else if (value instanceof Integer) - setInt(caller, object, ((Integer) value).intValue()); + setInt(caller, object, ((Integer) value).intValue(), true); else if (value instanceof Long) - setLong(caller, object, ((Long) value).longValue()); + setLong(caller, object, ((Long) value).longValue(), true); else if (value instanceof Float) - setFloat(caller, object, ((Float) value).floatValue()); + setFloat(caller, object, ((Float) value).floatValue(), true); else if (value instanceof Double) - setDouble(caller, object, ((Double) value).doubleValue()); + setDouble(caller, object, ((Double) value).doubleValue(), true); else if (value instanceof Character) - setChar(caller, object, ((Character) value).charValue()); + setChar(caller, object, ((Character) value).charValue(), true); else if (value instanceof Boolean) - setBoolean(caller, object, ((Boolean) value).booleanValue()); + setBoolean(caller, object, ((Boolean) value).booleanValue(), true); else throw new IllegalArgumentException(); } diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc index 7eb0322..9a8107b 100644 --- a/libjava/java/lang/reflect/natField.cc +++ b/libjava/java/lang/reflect/natField.cc @@ -45,14 +45,19 @@ java::lang::reflect::Field::getName () jclass java::lang::reflect::Field::getType () { - jfieldID fld = _Jv_FromReflectedField (this); - JvSynchronize sync (declaringClass); - _Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ()); - return fld->type; + if (type == NULL) + { + jfieldID fld = _Jv_FromReflectedField (this); + JvSynchronize sync (declaringClass); + _Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ()); + type = fld->type; + } + return type; } static void* -getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj) +getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj, + jboolean checkFinal) { // FIXME: we know CALLER is NULL here. At one point we planned to // have the compiler insert the caller as a hidden argument in some @@ -63,6 +68,12 @@ getAddr (java::lang::reflect::Field* field, jclass caller, jobject obj) jfieldID fld = _Jv_FromReflectedField (field); _Jv_ushort flags = fld->getModifiers(); + + // Setting a final field is usually not allowed. + if (checkFinal + && field->getModifiers() & java::lang::reflect::Modifier::FINAL) + throw new java::lang::IllegalAccessException(JvNewStringUTF + ("Field is final")); // Check accessibility, if required. if (! (Modifier::isPublic (flags) || field->isAccessible())) @@ -180,56 +191,56 @@ getDouble (jclass cls, void* addr) jboolean java::lang::reflect::Field::getBoolean (jclass caller, jobject obj) { - return ::getBoolean (this->getType(), getAddr (this, caller, obj)); + return ::getBoolean (this->getType(), getAddr (this, caller, obj, false)); } jchar java::lang::reflect::Field::getChar (jclass caller, jobject obj) { - return ::getChar (this->getType(), getAddr (this, caller, obj)); + return ::getChar (this->getType(), getAddr (this, caller, obj, false)); } jbyte java::lang::reflect::Field::getByte (jclass caller, jobject obj) { - return ::getByte (this->getType(), getAddr (this, caller, obj)); + return ::getByte (this->getType(), getAddr (this, caller, obj, false)); } jshort java::lang::reflect::Field::getShort (jclass caller, jobject obj) { - return ::getShort (this->getType(), getAddr (this, caller, obj)); + return ::getShort (this->getType(), getAddr (this, caller, obj, false)); } jint java::lang::reflect::Field::getInt (jclass caller, jobject obj) { - return ::getInt (this->getType(), getAddr (this, caller, obj)); + return ::getInt (this->getType(), getAddr (this, caller, obj, false)); } jlong java::lang::reflect::Field::getLong (jclass caller, jobject obj) { - return ::getLong (this->getType(), getAddr (this, caller, obj)); + return ::getLong (this->getType(), getAddr (this, caller, obj, false)); } jfloat java::lang::reflect::Field::getFloat (jclass caller, jobject obj) { - return ::getFloat (this->getType(), getAddr (this, caller, obj)); + return ::getFloat (this->getType(), getAddr (this, caller, obj, false)); } jdouble java::lang::reflect::Field::getDouble (jclass caller, jobject obj) { - return ::getDouble (this->getType(), getAddr (this, caller, obj)); + return ::getDouble (this->getType(), getAddr (this, caller, obj, false)); } jobject java::lang::reflect::Field::get (jclass caller, jobject obj) { jclass type = this->getType(); - void* addr = getAddr (this, caller, obj); + void* addr = getAddr (this, caller, obj, false); if (! type->isPrimitive ()) return * (jobject*) addr; if (type == JvPrimClass (double)) @@ -257,16 +268,6 @@ java::lang::reflect::Field::get (jclass caller, jobject obj) throw new java::lang::IllegalArgumentException; } -static void* -setAddr (java::lang::reflect::Field* field, jclass caller, jobject obj) -{ - void *addr = getAddr(field, caller, obj); - if (!field->isAccessible() - && field->getModifiers() & java::lang::reflect::Modifier::FINAL) - throw new java::lang::IllegalAccessException(); - return addr; -} - static void setBoolean (jclass type, void *addr, jboolean value) { @@ -378,57 +379,66 @@ setDouble (jclass type, void *addr, jdouble value) } void -java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b) +java::lang::reflect::Field::setBoolean (jclass caller, jobject obj, jboolean b, + jboolean checkFinal) { - ::setBoolean (this->getType(), setAddr (this, caller, obj), b); + ::setBoolean (this->getType(), getAddr (this, caller, obj, checkFinal), b); } void -java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c) +java::lang::reflect::Field::setChar (jclass caller, jobject obj, jchar c, + jboolean checkFinal) { - ::setChar (this->getType(), setAddr (this, caller, obj), c); + ::setChar (this->getType(), getAddr (this, caller, obj, checkFinal), c); } void -java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b) +java::lang::reflect::Field::setByte (jclass caller, jobject obj, jbyte b, + jboolean checkFinal) { - ::setByte (this->getType(), setAddr (this, caller, obj), b); + ::setByte (this->getType(), getAddr (this, caller, obj, checkFinal), b); } void -java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s) +java::lang::reflect::Field::setShort (jclass caller, jobject obj, jshort s, + jboolean checkFinal) { - ::setShort (this->getType(), setAddr (this, caller, obj), s); + ::setShort (this->getType(), getAddr (this, caller, obj, checkFinal), s); } void -java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i) +java::lang::reflect::Field::setInt (jclass caller, jobject obj, jint i, + jboolean checkFinal) { - ::setInt (this->getType(), setAddr (this, caller, obj), i); + ::setInt (this->getType(), getAddr (this, caller, obj, checkFinal), i); } void -java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l) +java::lang::reflect::Field::setLong (jclass caller, jobject obj, jlong l, + jboolean checkFinal) { - ::setLong (this->getType(), setAddr (this, caller, obj), l); + ::setLong (this->getType(), getAddr (this, caller, obj, checkFinal), l); } + void -java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f) +java::lang::reflect::Field::setFloat (jclass caller, jobject obj, jfloat f, + jboolean checkFinal) { - ::setFloat (this->getType(), setAddr (this, caller, obj), f); + ::setFloat (this->getType(), getAddr (this, caller, obj, checkFinal), f); } void -java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d) +java::lang::reflect::Field::setDouble (jclass caller, jobject obj, jdouble d, + jboolean checkFinal) { - ::setDouble (this->getType(), setAddr (this, caller, obj), d); + ::setDouble (this->getType(), getAddr (this, caller, obj, checkFinal), d); } void java::lang::reflect::Field::set (jclass caller, jobject object, jobject value, - jclass type) + jclass type, jboolean checkFinal) { - void* addr = setAddr (this, caller, object); + void* addr = getAddr (this, caller, object, checkFinal); if (value != NULL && ! _Jv_IsInstanceOf (value, type)) throw new java::lang::IllegalArgumentException; * (jobject*) addr = value; |