Re: Object serialization and final fields

2004-04-06 Thread Guilhem Lavaux
Mark Wielaard wrote:
Hi Guilhem,

On Fri, 2004-04-02 at 21:52, Guilhem Lavaux wrote:

Here is the real patch for object serialization. I've added new static 
methods to VMObjectStreamClass and changed the methods called in 
ObjectStreamField accordingly. Note that we need to check all exceptions 
now as the native functions may fail for some other obscure reasons.

2004-04-02  Guilhem Lavaux [EMAIL PROTECTED]

* java/io/ObjectStreamField.java
(setBooleanField, setCharField, setByteField, setShortField,
setIntField, setLongField, setFloatField, setDoubleField): Use
native methods directly to be able to set final fields.
* vm/reference/java/io/VMObjectStreamClass.java
(setBooleanNative, setCharNative, setByteNative, setShortNative,
setIntNative, setLongNative, setFloatNative, setDoubleNative):
New methods for serialization to be able to set final fields.
* native/jni/java-io/java_io_VMObjectStreamClass.c:
Implemented new native methods of java.io.VMObjectStreamClass
accordingly.
P.S.: If nobody is against, I'll check it in on sunday.


This looks very nice. Thanks.
Some nitpicks:
- You forgot the addition of setObjectNative() in the ChangeLog entry.
Ok.

- You should regenerate include/java_io_VMObjectStreamClass.h
  This is automatically done when configuring with
  --enable-regen-headers. But should be mentioned in the
  ChangeLog/patch.
Ok.

- Please chain exceptions. Don't just get the message, use initCause().
- Also catching Exception will miss Error (and subclasses) so you might
  want to catch Throwable.
Ok, I'm modifying this.

- But isn't it simpler to let the setXnative() methods throw
  InternalError() directly (or maybe VirtualMachineError or
  IllegalArgumentException which seem more appropriate).
- Then also don't declare the setXNative() methods throws
  IllegalAccessException. Some are declared as such and some not.
  But it seems this is the only exception that should never be thrown.
It was a mistake. First I wanted to make them throw nothing because I 
don't really know what may happen in the VM. At some point JNI calls may 
raise any type of exceptions. Maybe we may catch all exceptions directly 
 in the native code and only throw InternalError.



Could you also add a short notice to the NEWS file about this VM
interface change. You should at least mention that the standard
implementation assumes that the JNI setXField() methods can be used on
final fields.
Ok.

The mauve testcase is in CVS (added into 
gnu/testlet/java/io/ObjectInputOutput/Test).
Here is the new patch and the new changelog entry (hoping everything is 
alright now):

2004-04-06  Guilhem Lavaux [EMAIL PROTECTED]

* java/io/ObjectStreamField.java
(setBooleanField, setCharField, setByteField, setShortField,
setIntField, setLongField, setFloatField, setDoubleField,
setObjectField): Use native methods directly to be able to set
final fields.
* vm/reference/java/io/VMObjectStreamClass.java
(setBooleanNative, setCharNative, setByteNative, setShortNative,
setIntNative, setLongNative, setFloatNative, setDoubleNative,
setObjectNative): New methods for serialization to be able to
set final fields.
* native/jni/java-io/java_io_VMObjectStreamClass.c:
Implemented new native methods of java.io.VMObjectStreamClass
accordingly.
	* include/java_io_VMObjectStreamClass.h: Regenerated.

	* NEWS: Added a warning clause about the VM Interface change.

Cheers,

Guilhem.
Index: NEWS
===
RCS file: /cvsroot/classpath/classpath/NEWS,v
retrieving revision 1.36
diff -u -b -B -r1.36 NEWS
--- NEWS13 Mar 2004 02:18:39 -  1.36
+++ NEWS6 Apr 2004 19:55:20 -
@@ -1,3 +1,11 @@
+New in release 0.09
+
+VM Interface changes:
+
+* GNU Classpath now assumes that JNI calls SetXField can modify final
+fields. This was previously used silently for System.in/out/err and should
+be considered as a feature now. 
+
 New in release 0.08 (2004/12/03)
 
 * java.util.regexp implementation through gnu.regexp wrappers.
Index: native/jni/java-io/java_io_VMObjectStreamClass.c
===
RCS file: 
/cvsroot/classpath/classpath/native/jni/java-io/java_io_VMObjectStreamClass.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 java_io_VMObjectStreamClass.c
--- native/jni/java-io/java_io_VMObjectStreamClass.c29 Mar 2004 07:07:27 - 
 1.3
+++ native/jni/java-io/java_io_VMObjectStreamClass.c6 Apr 2004 19:55:20 -
@@ -59,3 +59,238 @@
 }
   return JNI_TRUE;
 }
+
+static void throwInternalError(JNIEnv *env)
+{
+  jclass internalErrorClass;
+  jthrowable previousException, newException;
+  jmethodID initException, getMessageID, initCauseID;
+  jstring message;
+
+  internalErrorClass = (*env)-FindClass(env, java/lang/InternalError);
+ 

Re: Object serialization and final fields

2004-04-04 Thread Mark Wielaard
Hi Guilhem,

On Fri, 2004-04-02 at 21:52, Guilhem Lavaux wrote:
 Here is the real patch for object serialization. I've added new static 
 methods to VMObjectStreamClass and changed the methods called in 
 ObjectStreamField accordingly. Note that we need to check all exceptions 
 now as the native functions may fail for some other obscure reasons.

 2004-04-02  Guilhem Lavaux [EMAIL PROTECTED]
 
   * java/io/ObjectStreamField.java
   (setBooleanField, setCharField, setByteField, setShortField,
   setIntField, setLongField, setFloatField, setDoubleField): Use
   native methods directly to be able to set final fields.
 
   * vm/reference/java/io/VMObjectStreamClass.java
   (setBooleanNative, setCharNative, setByteNative, setShortNative,
   setIntNative, setLongNative, setFloatNative, setDoubleNative):
   New methods for serialization to be able to set final fields.
 
   * native/jni/java-io/java_io_VMObjectStreamClass.c:
   Implemented new native methods of java.io.VMObjectStreamClass
   accordingly.

 P.S.: If nobody is against, I'll check it in on sunday.

This looks very nice. Thanks.
Some nitpicks:

- You forgot the addition of setObjectNative() in the ChangeLog entry.
- You should regenerate include/java_io_VMObjectStreamClass.h
  This is automatically done when configuring with
  --enable-regen-headers. But should be mentioned in the
  ChangeLog/patch.
- Please chain exceptions. Don't just get the message, use initCause().
- Also catching Exception will miss Error (and subclasses) so you might
  want to catch Throwable.
- But isn't it simpler to let the setXnative() methods throw
  InternalError() directly (or maybe VirtualMachineError or
  IllegalArgumentException which seem more appropriate).
- Then also don't declare the setXNative() methods throws
  IllegalAccessException. Some are declared as such and some not.
  But it seems this is the only exception that should never be thrown.

Could you also add a short notice to the NEWS file about this VM
interface change. You should at least mention that the standard
implementation assumes that the JNI setXField() methods can be used on
final fields.

BTW. Note to VM/Compiler implementers!
--
We discussed final fields a bit more on irc.
We came to the conclusion the the VM spec authors and the JLS spec
authors have a different interpretation of final.
According to the VM spec a final field is non-private read-only, but
rewritable by the Class defining the field.
According the the JLS spec a final field is single assignable (in a
[static] constructor method).
JNI doesn't seem to define precisely what/how final fields can change.
The above patch depends on the fact that in practice JNI setXField() can
be used to set a final field (this was already the case for the
System.setIn()/setOut()/setError() methods).

The following bug reports are also interesting:

http://developer.java.sun.com/developer/bugParade/bugs/4027808.html
Synopsis: [JNI] SetObjectField modifies a final field value
State: Closed, will not be fixed
Evaluation: JNI does not guard against illegal access to objects [...].

http://developer.java.sun.com/developer/bugParade/bugs/4115974.html
Synopsis: Need to be able to tell JIT not to optimize certain finals.
State: Closed, will not be fixed
Evaluation: These are the only thing which should ever behave this way,
so there's no need for a special interface for this.  The JIT just needs
to handle these specially.

http://developer.java.sun.com/developer/bugParade/bugs/4174797.html
Synopsis: Serialization should not use reflection to set final fields
State: Closed, fixed
Evaluation: [...] Serialization needs to use JNI SettypeField Routines
to set fields, instead of Field.set*(). [...]

All this seems a bit unfortunate since it basically means that a runtime
cannot optimize final field access since they can always be changed
through JNI and this feature is at least necessary for both
System.setIn/Out/Err() and reflection.

Cheers,

Mark


signature.asc
Description: This is a digitally signed message part
___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath


Re: Object serialization and final fields

2004-04-04 Thread Mark Wielaard
Hi,

On Sun, 2004-04-04 at 20:01, Mark Wielaard wrote:
 This looks very nice. Thanks.
 Some nitpicks:
 [...]

Last nitpick. I promise!
- Do you have a test case that can be added to Mauve?

Thanks,

Mark


signature.asc
Description: This is a digitally signed message part
___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath


RE: Object serialization and final fields

2004-04-04 Thread David Holmes
Mark Wielaard wrote:
 BTW. Note to VM/Compiler implementers!
 --
 We discussed final fields a bit more on irc.
 We came to the conclusion the the VM spec authors and the JLS spec
 authors have a different interpretation of final.
 According to the VM spec a final field is non-private read-only, but
 rewritable by the Class defining the field.
 According the the JLS spec a final field is single assignable (in a
 [static] constructor method).
 JNI doesn't seem to define precisely what/how final fields can change.
 The above patch depends on the fact that in practice JNI setXField() can
 be used to set a final field (this was already the case for the
 System.setIn()/setOut()/setError() methods).

 The following bug reports are also interesting:

 http://developer.java.sun.com/developer/bugParade/bugs/4027808.html
 Synopsis: [JNI] SetObjectField modifies a final field value
 State: Closed, will not be fixed
 Evaluation: JNI does not guard against illegal access to objects [...].

 http://developer.java.sun.com/developer/bugParade/bugs/4115974.html
 Synopsis: Need to be able to tell JIT not to optimize certain finals.
 State: Closed, will not be fixed
 Evaluation: These are the only thing which should ever behave this way,
 so there's no need for a special interface for this.  The JIT just needs
 to handle these specially.

 http://developer.java.sun.com/developer/bugParade/bugs/4174797.html
 Synopsis: Serialization should not use reflection to set final fields
 State: Closed, fixed
 Evaluation: [...] Serialization needs to use JNI SettypeField Routines
 to set fields, instead of Field.set*(). [...]

 All this seems a bit unfortunate since it basically means that a runtime
 cannot optimize final field access since they can always be changed
 through JNI and this feature is at least necessary for both
 System.setIn/Out/Err() and reflection.

These issues may be addressed in the near future - though it is a bit of a
mess. The new Java Memory Model basically allows all the optimisations you
want and says that native modification of final fields, beyond use of
SetIn/Out/Err, need not cause a change by one thread to become visible in
another. In other words any application using this is on its own. There are
also special rules for handling the deserialisation issue with finals.

See http://www.cs.umd.edu/~pugh/java/memoryModel for details.

David Holmes



___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath


Re: Object serialization and final fields

2004-04-02 Thread Guilhem Lavaux
Hi,

Here is the real patch for object serialization. I've added new static 
methods to VMObjectStreamClass and changed the methods called in 
ObjectStreamField accordingly. Note that we need to check all exceptions 
now as the native functions may fail for some other obscure reasons.

ChangeLog entry:

2004-04-02  Guilhem Lavaux [EMAIL PROTECTED]

* java/io/ObjectStreamField.java
(setBooleanField, setCharField, setByteField, setShortField,
setIntField, setLongField, setFloatField, setDoubleField): Use
native methods directly to be able to set final fields.
* vm/reference/java/io/VMObjectStreamClass.java
(setBooleanNative, setCharNative, setByteNative, setShortNative,
setIntNative, setLongNative, setFloatNative, setDoubleNative):
New methods for serialization to be able to set final fields.
* native/jni/java-io/java_io_VMObjectStreamClass.c:
Implemented new native methods of java.io.VMObjectStreamClass
accordingly.
Cheers,

Guilhem.

P.S.: If nobody is against, I'll check it in on sunday.
Index: java/io/ObjectStreamField.java
===
RCS file: /cvsroot/classpath/classpath/java/io/ObjectStreamField.java,v
retrieving revision 1.14
diff -u -b -B -r1.14 ObjectStreamField.java
--- java/io/ObjectStreamField.java  26 Feb 2004 07:53:15 -  1.14
+++ java/io/ObjectStreamField.java  2 Apr 2004 19:42:15 -
@@ -38,9 +38,9 @@
 
 package java.io;
 
+import gnu.java.lang.reflect.TypeSignature;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import gnu.java.lang.reflect.TypeSignature;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 
@@ -64,7 +64,6 @@
   {
 this (field.getName(), field.getType());
 this.field = field;
-toset = !Modifier.isFinal(field.getModifiers());
   }
 
   /**
@@ -357,9 +356,9 @@
   {
 try
   {
-   field.setBoolean(obj, val);
+   VMObjectStreamClass.setBooleanNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -369,9 +368,9 @@
   {
 try
   {
-   field.setByte(obj, val);
+   VMObjectStreamClass.setByteNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -381,9 +380,9 @@
   {
 try
   {
-   field.setChar(obj, val);
+   VMObjectStreamClass.setCharNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -393,9 +392,9 @@
   {
 try
   {
-   field.setShort(obj, val);
+   VMObjectStreamClass.setShortNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -405,9 +404,9 @@
   {
 try
   {
-   field.setInt(obj, val);
+   VMObjectStreamClass.setIntNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -417,9 +416,9 @@
   {
 try
   {
-   field.setLong(obj, val);
+   VMObjectStreamClass.setLongNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -429,9 +428,9 @@
   {
 try
   {
-   field.setFloat(obj, val);
+   VMObjectStreamClass.setFloatNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
@@ -441,21 +440,22 @@
   {
 try
   {
-   field.setDouble(obj, val);
+   VMObjectStreamClass.setDoubleNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
   }
   
+  
   final void setObjectField(Object obj, Object val)
   { 
 try
   {
-   field.set(obj, val);
+   VMObjectStreamClass.setObjectNative(field, obj, val);
   }
-catch(IllegalAccessException x)
+catch(Exception x)
   {
throw new InternalError(x.getMessage());
   }
Index: native/jni/java-io/java_io_VMObjectStreamClass.c
===
RCS file: 
/cvsroot/classpath/classpath/native/jni/java-io/java_io_VMObjectStreamClass.c,v
retrieving revision 1.3
diff -u -b -B -r1.3 java_io_VMObjectStreamClass.c
--- native/jni/java-io/java_io_VMObjectStreamClass.c29 Mar 2004 07:07:27 - 
 1.3
+++ native/jni/java-io/java_io_VMObjectStreamClass.c2 Apr 2004 19:42:17 -
@@ -59,3 +59,195 @@
 }
   return JNI_TRUE;
 }
+
+static jfieldID getFieldReference(JNIEnv 

Re: Object serialization and final fields

2004-03-29 Thread Guilhem Lavaux
Mark Wielaard wrote:
Hi,

Hi Mark !

On Thu, 2004-03-25 at 21:19, Guilhem Lavaux wrote: 

Some people has reported failures in kaffe with applications trying to 
deserialize objects containing final fields. Apparently it is authorized 
 in the serialization spec but we cannot rely on 
java.lang.reflect.Field to set them. So our only solution is to bypass 
the protection in java.lang.reflect.Field by creating new native calls 
in ObjectStreamField.

I am proposing the following changes for ObjectStreamField.


It is a bit sad that serialization needs a couple of things that clearly
should have been standard reflection methods/options. Sigh.
I like the idea in general.
Couple of comments/questions.
- ChangeLog entry is missing...

Well, it was not a final patch but just to open up the discussion.

@@ -64,7 +65,7 @@
  {
this (field.getName(), field.getType());
this.field = field;
-toset = !Modifier.isFinal(field.getModifiers());
+//toset = !Modifier.isFinal(field.getModifiers());
  }


Either remove this or make it a real comment explaining why we don't
test this anymore.
Ok, will do it asap.



  /**
@@ -353,11 +354,14 @@
return ObjectStreamField  + type +   + name +  ;
  }
+  final private native void setBooleanNative(Object obj, boolean val) 
+throws IllegalAccessException;
+


This and the other setXXXNative methods should be moved to
VMObjectStreamClass. You should also provide sample JNI implementations
for this in native/jni/java-io/java_io_VMObjectStreamClass.c
(Note that VmSystem.c has examples for this. See VMSystem
setIn/Out/Err())
Maybe make them static and also provide the field object?

I'll do as requested but concerning java_io_VMObjectStreamClass.c I 
would like to propose something else.
After more experimentation, I would have preferred to have some private 
internal methods in java.lang.reflect.Field which we could call directly 
from native code. These calls should not check whether a field is final 
or not but just try to set it. The other usual methods of Field 
(get/set) should check the final bit and call the internal methods 
afterwards.

If it's not possible I will borrow some code from native Field 
implementation.


  final void setBooleanField(Object obj, boolean val)
  {
try
  {
-   field.setBoolean(obj, val);
+   setBooleanNative(obj, val);
  }
catch(IllegalAccessException x)
  {


Do we want to use the new method unconditionally or only when the field
is final?
Would it be useful ? I think it would only eat CPU as we always need to 
set fields.

Cheers,

Guilhem.



___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath


Re: Object serialization and final fields

2004-03-28 Thread Mark Wielaard
Hi,

On Thu, 2004-03-25 at 21:19, Guilhem Lavaux wrote: 
 Some people has reported failures in kaffe with applications trying to 
 deserialize objects containing final fields. Apparently it is authorized 
   in the serialization spec but we cannot rely on 
 java.lang.reflect.Field to set them. So our only solution is to bypass 
 the protection in java.lang.reflect.Field by creating new native calls 
 in ObjectStreamField.
 
 I am proposing the following changes for ObjectStreamField.

It is a bit sad that serialization needs a couple of things that clearly
should have been standard reflection methods/options. Sigh.

I like the idea in general.
Couple of comments/questions.

- ChangeLog entry is missing...

 Index: java/io/ObjectStreamField.java
 ===
 RCS file: /cvsroot/classpath/classpath/java/io/ObjectStreamField.java,v
 retrieving revision 1.14
 diff -u -b -B -r1.14 ObjectStreamField.java
 -- java/io/ObjectStreamField.java 26 Feb 2004 07:53:15 -  1.14
 +++ java/io/ObjectStreamField.java25 Mar 2004 20:19:43 -
 @@ -38,9 +38,10 @@
  
  package java.io;
  
 +import gnu.java.lang.reflect.TypeSignature;
 +
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
 -import gnu.java.lang.reflect.TypeSignature;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  
 @@ -64,7 +65,7 @@
{
  this (field.getName(), field.getType());
  this.field = field;
 -toset = !Modifier.isFinal(field.getModifiers());
 +//toset = !Modifier.isFinal(field.getModifiers());
}

Either remove this or make it a real comment explaining why we don't
test this anymore.

/**
 @@ -353,11 +354,14 @@
  return ObjectStreamField  + type +   + name +  ;
}
  
 +  final private native void setBooleanNative(Object obj, boolean val) 
 +throws IllegalAccessException;
 +

This and the other setXXXNative methods should be moved to
VMObjectStreamClass. You should also provide sample JNI implementations
for this in native/jni/java-io/java_io_VMObjectStreamClass.c
(Note that VmSystem.c has examples for this. See VMSystem
setIn/Out/Err())

Maybe make them static and also provide the field object?

final void setBooleanField(Object obj, boolean val)
{
  try
{
 - field.setBoolean(obj, val);
 + setBooleanNative(obj, val);
}
  catch(IllegalAccessException x)
{

Do we want to use the new method unconditionally or only when the field
is final?

Cheers,

Mark


signature.asc
Description: This is a digitally signed message part
___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath