8164908: ReflectionFactory support for IIOP and custom serialization

Update IIOP Streams to use ReflectionFactory and Unsafe

Reviewed-by: alanb, chegar, plevart, amlu
This commit is contained in:
Roger Riggs 2016-10-24 14:53:29 -04:00
parent a4cf9a8666
commit bc7cb4bb75
6 changed files with 236 additions and 415 deletions

View File

@ -31,22 +31,17 @@
package com.sun.corba.se.impl.io; package com.sun.corba.se.impl.io;
import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.StreamCorruptedException; import java.io.StreamCorruptedException;
import java.io.ObjectInputValidation; import java.io.ObjectInputValidation;
import java.io.NotActiveException; import java.io.NotActiveException;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.InvalidClassException; import java.io.InvalidClassException;
import java.io.DataInputStream;
import java.io.OptionalDataException; import java.io.OptionalDataException;
import java.io.WriteAbortedException;
import java.io.Externalizable; import java.io.Externalizable;
import java.io.EOFException; import java.io.EOFException;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Vector; import java.util.Vector;
import java.util.Stack;
import java.util.Hashtable;
import java.util.Enumeration; import java.util.Enumeration;
import sun.corba.Bridge ; import sun.corba.Bridge ;
@ -54,7 +49,6 @@ import sun.corba.Bridge ;
import java.security.AccessController ; import java.security.AccessController ;
import java.security.PrivilegedAction ; import java.security.PrivilegedAction ;
import com.sun.corba.se.impl.io.ObjectStreamClass;
import com.sun.corba.se.impl.util.Utility; import com.sun.corba.se.impl.util.Utility;
import org.omg.CORBA.portable.ValueInputStream; import org.omg.CORBA.portable.ValueInputStream;
@ -71,14 +65,12 @@ import org.omg.CORBA.TypeCode;
import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription; import com.sun.org.omg.CORBA.ValueDefPackage.FullValueDescription;
import com.sun.org.omg.SendingContext.CodeBase; import com.sun.org.omg.SendingContext.CodeBase;
import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Util; import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandler; import javax.rmi.CORBA.ValueHandler;
import java.security.*; import java.security.*;
import java.util.*; import java.util.*;
import com.sun.corba.se.impl.orbutil.ObjectUtility ;
import com.sun.corba.se.impl.logging.OMGSystemException ; import com.sun.corba.se.impl.logging.OMGSystemException ;
import com.sun.corba.se.impl.logging.UtilSystemException ; import com.sun.corba.se.impl.logging.UtilSystemException ;
@ -182,75 +174,6 @@ public class IIOPInputStream
private byte streamFormatVersion; private byte streamFormatVersion;
// Since java.io.OptionalDataException's constructors are
// package private, but we need to throw it in some special
// cases, we try to do it by reflection.
private static final Constructor OPT_DATA_EXCEPTION_CTOR;
private Object[] readObjectArgList = { this } ;
static {
OPT_DATA_EXCEPTION_CTOR = getOptDataExceptionCtor();
}
// Grab the OptionalDataException boolean ctor and make
// it accessible. Note that any exceptions
// will be wrapped in ExceptionInInitializerErrors.
private static Constructor getOptDataExceptionCtor() {
try {
Constructor result =
(Constructor) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public java.lang.Object run()
throws NoSuchMethodException,
SecurityException {
Constructor boolCtor
= OptionalDataException.class.getDeclaredConstructor(
new Class[] {
Boolean.TYPE });
boolCtor.setAccessible(true);
return boolCtor;
}});
if (result == null)
// XXX I18N, logging needed.
throw new Error("Unable to find OptionalDataException constructor");
return result;
} catch (Exception ex) {
// XXX I18N, logging needed.
throw new ExceptionInInitializerError(ex);
}
}
// Create a new OptionalDataException with the EOF marker
// set to true. See handleOptionalDataMarshalException.
private OptionalDataException createOptionalDataException() {
try {
OptionalDataException result
= (OptionalDataException)
OPT_DATA_EXCEPTION_CTOR.newInstance(new Object[] {
Boolean.TRUE });
if (result == null)
// XXX I18N, logging needed.
throw new Error("Created null OptionalDataException");
return result;
} catch (Exception ex) {
// XXX I18N, logging needed.
throw new Error("Couldn't create OptionalDataException", ex);
}
}
// Return the stream format version currently being used // Return the stream format version currently being used
// to deserialize an object // to deserialize an object
protected byte getStreamFormatVersion() { protected byte getStreamFormatVersion() {
@ -395,7 +318,6 @@ public class IIOPInputStream
int offset) int offset)
/* throws OptionalDataException, ClassNotFoundException, IOException */ /* throws OptionalDataException, ClassNotFoundException, IOException */
{ {
/* Save the current state and get ready to read an object. */ /* Save the current state and get ready to read an object. */
Object prevObject = currentObject; Object prevObject = currentObject;
ObjectStreamClass prevClassDesc = currentClassDesc; ObjectStreamClass prevClassDesc = currentClassDesc;
@ -947,7 +869,7 @@ public class IIOPInputStream
if (!objectRead) if (!objectRead)
result = new EOFException("No more optional data"); result = new EOFException("No more optional data");
else else
result = createOptionalDataException(); result = bridge.newOptionalDataExceptionForSerialization(true);
result.initCause(marshalException); result.initCause(marshalException);
@ -1230,8 +1152,7 @@ public class IIOPInputStream
readObjectState.beginUnmarshalCustomValue(this, readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject, calledDefaultWriteObject,
(currentClassDesc.readObjectMethod currentClassDesc.hasReadObject());
!= null));
} else { } else {
if (currentClassDesc.hasReadObject()) if (currentClassDesc.hasReadObject())
setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED); setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
@ -1556,8 +1477,7 @@ public class IIOPInputStream
readObjectState.beginUnmarshalCustomValue(this, readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject, calledDefaultWriteObject,
(currentClassDesc.readObjectMethod currentClassDesc.hasReadObject());
!= null));
} }
boolean usedReadObject = false; boolean usedReadObject = false;
@ -1714,13 +1634,8 @@ public class IIOPInputStream
throws InvalidClassException, StreamCorruptedException, throws InvalidClassException, StreamCorruptedException,
ClassNotFoundException, IOException ClassNotFoundException, IOException
{ {
if (osc.readObjectMethod == null) {
return false;
}
try { try {
osc.readObjectMethod.invoke( obj, readObjectArgList ) ; return osc.invokeReadObject( obj, this ) ;
return true;
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
Throwable t = e.getTargetException(); Throwable t = e.getTargetException();
if (t instanceof ClassNotFoundException) if (t instanceof ClassNotFoundException)
@ -1734,8 +1649,6 @@ public class IIOPInputStream
else else
// XXX I18N, logging needed. // XXX I18N, logging needed.
throw new Error("internal error"); throw new Error("internal error");
} catch (IllegalAccessException e) {
return false;
} }
} }

View File

@ -31,33 +31,23 @@
package com.sun.corba.se.impl.io; package com.sun.corba.se.impl.io;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.portable.OutputStream; import org.omg.CORBA.portable.OutputStream;
import java.security.AccessController ; import java.security.AccessController ;
import java.security.PrivilegedAction ; import java.security.PrivilegedAction ;
import java.io.IOException; import java.io.IOException;
import java.io.DataOutputStream;
import java.io.Serializable;
import java.io.InvalidClassException; import java.io.InvalidClassException;
import java.io.StreamCorruptedException;
import java.io.Externalizable; import java.io.Externalizable;
import java.io.ObjectStreamException;
import java.io.NotSerializableException; import java.io.NotSerializableException;
import java.io.NotActiveException; import java.io.NotActiveException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import java.util.Stack;
import javax.rmi.CORBA.Util; import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandlerMultiFormat;
import sun.corba.Bridge ; import sun.corba.Bridge ;
import com.sun.corba.se.impl.io.ObjectStreamClass;
import com.sun.corba.se.impl.util.Utility; import com.sun.corba.se.impl.util.Utility;
import com.sun.corba.se.impl.util.RepositoryId; import com.sun.corba.se.impl.util.RepositoryId;
@ -621,7 +611,7 @@ public class IIOPOutputStream
writeObjectState.enterWriteObject(this); writeObjectState.enterWriteObject(this);
// writeObject(obj, c, this); // writeObject(obj, c, this);
osc.writeObjectMethod.invoke( obj, writeObjectArgList ) ; osc.invokeWriteObject( obj, this ) ;
writeObjectState.exitWriteObject(this); writeObjectState.exitWriteObject(this);
@ -636,8 +626,6 @@ public class IIOPOutputStream
else else
// XXX I18N, Logging needed. // XXX I18N, Logging needed.
throw new Error("invokeObjectWriter internal error",e); throw new Error("invokeObjectWriter internal error",e);
} catch (IllegalAccessException e) {
// cannot happen
} }
} }
@ -761,59 +749,52 @@ public class IIOPOutputStream
*/ */
private void outputClassFields(Object o, Class cl, private void outputClassFields(Object o, Class cl,
ObjectStreamField[] fields) ObjectStreamField[] fields)
throws IOException, InvalidClassException { throws IOException {
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
if (fields[i].getField() == null) if (fields[i].getField() == null)
// XXX I18N, Logging needed.
throw new InvalidClassException(cl.getName(), throw new InvalidClassException(cl.getName(),
"Nonexistent field " + fields[i].getName()); "Nonexistent field " + fields[i].getName());
switch (fields[i].getTypeCode()) {
try { case 'B':
switch (fields[i].getTypeCode()) { byte byteValue = bridge.getByte(o, fields[i].getFieldID()) ;
case 'B': orbStream.write_octet(byteValue);
byte byteValue = fields[i].getField().getByte( o ) ; break;
orbStream.write_octet(byteValue); case 'C':
break; char charValue = bridge.getChar(o, fields[i].getFieldID()) ;
case 'C': orbStream.write_wchar(charValue);
char charValue = fields[i].getField().getChar( o ) ; break;
orbStream.write_wchar(charValue); case 'F':
break; float floatValue = bridge.getFloat(o, fields[i].getFieldID()) ;
case 'F': orbStream.write_float(floatValue);
float floatValue = fields[i].getField().getFloat( o ) ; break;
orbStream.write_float(floatValue); case 'D' :
break; double doubleValue = bridge.getDouble(o, fields[i].getFieldID()) ;
case 'D' : orbStream.write_double(doubleValue);
double doubleValue = fields[i].getField().getDouble( o ) ; break;
orbStream.write_double(doubleValue); case 'I':
break; int intValue = bridge.getInt(o, fields[i].getFieldID()) ;
case 'I': orbStream.write_long(intValue);
int intValue = fields[i].getField().getInt( o ) ; break;
orbStream.write_long(intValue); case 'J':
break; long longValue = bridge.getLong(o, fields[i].getFieldID()) ;
case 'J': orbStream.write_longlong(longValue);
long longValue = fields[i].getField().getLong( o ) ; break;
orbStream.write_longlong(longValue); case 'S':
break; short shortValue = bridge.getShort(o, fields[i].getFieldID()) ;
case 'S': orbStream.write_short(shortValue);
short shortValue = fields[i].getField().getShort( o ) ; break;
orbStream.write_short(shortValue); case 'Z':
break; boolean booleanValue = bridge.getBoolean(o, fields[i].getFieldID()) ;
case 'Z': orbStream.write_boolean(booleanValue);
boolean booleanValue = fields[i].getField().getBoolean( o ) ; break;
orbStream.write_boolean(booleanValue); case '[':
break; case 'L':
case '[': Object objectValue = bridge.getObject(o, fields[i].getFieldID()) ;
case 'L': writeObjectField(fields[i], objectValue);
Object objectValue = fields[i].getField().get( o ) ; break;
writeObjectField(fields[i], objectValue); default:
break; throw new InvalidClassException(cl.getName());
default:
// XXX I18N, Logging needed.
throw new InvalidClassException(cl.getName());
}
} catch (IllegalAccessException exc) {
throw wrapper.illegalFieldAccess( exc, fields[i].getName() ) ;
} }
} }
} }

View File

@ -31,16 +31,16 @@
package com.sun.corba.se.impl.io; package com.sun.corba.se.impl.io;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.invoke.MethodHandle;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.DigestOutputStream; import java.security.DigestOutputStream;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Array;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -80,9 +80,6 @@ public class ObjectStreamClass implements java.io.Serializable {
public static final long kDefaultUID = -1; public static final long kDefaultUID = -1;
private static Object noArgsList[] = {};
private static Class<?> noTypesList[] = {};
/** true if represents enum type */ /** true if represents enum type */
private boolean isEnum; private boolean isEnum;
@ -311,12 +308,37 @@ public class ObjectStreamClass implements java.io.Serializable {
return null; return null;
} }
public final boolean invokeWriteObject(Object obj, ObjectOutputStream ois) throws InvocationTargetException {
if (!hasWriteObject()) {
return false;
}
try {
writeObjectMethod.invoke(obj, ois);
} catch (Throwable t) {
throw new InvocationTargetException(t, "writeObject");
}
return true;
}
public final boolean invokeReadObject(Object obj, ObjectInputStream ois) throws InvocationTargetException {
if (hasReadObject()) {
try {
readObjectMethod.invoke(obj, ois);
return true;
} catch (Throwable t) {
throw new InvocationTargetException(t, "readObject");
}
} else {
return false;
}
}
public Serializable writeReplace(Serializable value) { public Serializable writeReplace(Serializable value) {
if (writeReplaceObjectMethod != null) { if (writeReplaceObjectMethod != null) {
try { try {
return (Serializable) writeReplaceObjectMethod.invoke(value,noArgsList); return (Serializable) writeReplaceObjectMethod.invoke(value);
} catch(Throwable t) { } catch (Throwable t) {
throw new RuntimeException(t); throw new InternalError("unexpected error", t);
} }
} }
else return value; else return value;
@ -325,9 +347,9 @@ public class ObjectStreamClass implements java.io.Serializable {
public Object readResolve(Object value) { public Object readResolve(Object value) {
if (readResolveObjectMethod != null) { if (readResolveObjectMethod != null) {
try { try {
return readResolveObjectMethod.invoke(value,noArgsList); return readResolveObjectMethod.invoke(value);
} catch(Throwable t) { } catch (Throwable t) {
throw new RuntimeException(t); throw new InternalError("unexpected error", t);
} }
} }
else return value; else return value;
@ -382,31 +404,34 @@ public class ObjectStreamClass implements java.io.Serializable {
*/ */
} }
private static final class PersistentFieldsValue static final class PersistentFieldsValue
extends ClassValue<ObjectStreamField[]> { extends ClassValue<ObjectStreamField[]> {
PersistentFieldsValue() { } PersistentFieldsValue() { }
protected ObjectStreamField[] computeValue(Class<?> type) { protected ObjectStreamField[] computeValue(Class<?> type) {
try { try {
bridge.ensureClassInitialized(type);
Field pf = type.getDeclaredField("serialPersistentFields"); Field pf = type.getDeclaredField("serialPersistentFields");
int mods = pf.getModifiers(); int mods = pf.getModifiers();
if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) && if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) &&
Modifier.isFinal(mods)) { Modifier.isFinal(mods)) {
pf.setAccessible(true); long offset = bridge.staticFieldOffset(pf);
java.io.ObjectStreamField[] fields = java.io.ObjectStreamField[] fields =
(java.io.ObjectStreamField[])pf.get(type); (java.io.ObjectStreamField[])bridge.getObject(type, offset);
return translateFields(fields); return translateFields(fields);
} }
} catch (NoSuchFieldException | IllegalAccessException | } catch (NoSuchFieldException |
IllegalArgumentException | ClassCastException e) { IllegalArgumentException | ClassCastException e) {
} }
return null; return null;
} }
private static ObjectStreamField[] translateFields( private static ObjectStreamField[] translateFields(java.io.ObjectStreamField[] fields) {
java.io.ObjectStreamField[] fields) { if (fields == null) {
return null;
}
ObjectStreamField[] translation = ObjectStreamField[] translation =
new ObjectStreamField[fields.length]; new ObjectStreamField[fields.length];
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
translation[i] = new ObjectStreamField(fields[i].getName(), translation[i] = new ObjectStreamField(fields[i].getName(),
fields[i].getType()); fields[i].getType());
@ -450,13 +475,11 @@ public class ObjectStreamClass implements java.io.Serializable {
* If it is declared, use the declared serialPersistentFields. * If it is declared, use the declared serialPersistentFields.
* Otherwise, extract the fields from the class itself. * Otherwise, extract the fields from the class itself.
*/ */
fields = persistentFieldsValue.get(cl); fields = persistentFieldsValue.get(cl);
if (fields == null) { if (fields == null) {
/* Get all of the declared fields for this /* Get all of the declared fields for this Class.
* Class. setAccessible on all fields so they * Create a temporary ObjectStreamField array to hold each
* can be accessed later. Create a temporary
* ObjectStreamField array to hold each
* non-static, non-transient field. Then copy the * non-static, non-transient field. Then copy the
* temporary array into an array of the correct * temporary array into an array of the correct
* size once the number of fields is known. * size once the number of fields is known.
@ -471,7 +494,6 @@ public class ObjectStreamClass implements java.io.Serializable {
int modifiers = fld.getModifiers(); int modifiers = fld.getModifiers();
if (!Modifier.isStatic(modifiers) && if (!Modifier.isStatic(modifiers) &&
!Modifier.isTransient(modifiers)) { !Modifier.isTransient(modifiers)) {
fld.setAccessible(true) ;
tempFields[numFields++] = new ObjectStreamField(fld); tempFields[numFields++] = new ObjectStreamField(fld);
} }
} }
@ -487,7 +509,6 @@ public class ObjectStreamClass implements java.io.Serializable {
try { try {
Field reflField = cl.getDeclaredField(fields[j].getName()); Field reflField = cl.getDeclaredField(fields[j].getName());
if (fields[j].getType() == reflField.getType()) { if (fields[j].getType() == reflField.getType()) {
reflField.setAccessible(true);
fields[j].setField(reflField); fields[j].setField(reflField);
} }
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
@ -527,8 +548,8 @@ public class ObjectStreamClass implements java.io.Serializable {
int mods = f.getModifiers(); int mods = f.getModifiers();
// SerialBug 5: static final SUID should be read // SerialBug 5: static final SUID should be read
if (Modifier.isStatic(mods) && Modifier.isFinal(mods) ) { if (Modifier.isStatic(mods) && Modifier.isFinal(mods) ) {
f.setAccessible(true); long offset = bridge.staticFieldOffset(f);
suid = f.getLong(cl); suid = bridge.getLong(cl, offset);
// SerialBug 2: should be computed after writeObject // SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl); // actualSuid = computeStructuralUID(cl);
} else { } else {
@ -540,16 +561,12 @@ public class ObjectStreamClass implements java.io.Serializable {
suid = _computeSerialVersionUID(cl); suid = _computeSerialVersionUID(cl);
// SerialBug 2: should be computed after writeObject // SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl); // actualSuid = computeStructuralUID(cl);
} catch (IllegalAccessException ex) {
suid = _computeSerialVersionUID(cl);
} }
} }
writeReplaceObjectMethod = ObjectStreamClass.getInheritableMethod(cl, writeReplaceObjectMethod = bridge.writeReplaceForSerialization(cl);
"writeReplace", noTypesList, Object.class);
readResolveObjectMethod = ObjectStreamClass.getInheritableMethod(cl, readResolveObjectMethod = bridge.readResolveForSerialization(cl);
"readResolve", noTypesList, Object.class);
if (externalizable) if (externalizable)
cons = getExternalizableConstructor(cl) ; cons = getExternalizableConstructor(cl) ;
@ -557,14 +574,8 @@ public class ObjectStreamClass implements java.io.Serializable {
cons = getSerializableConstructor(cl) ; cons = getSerializableConstructor(cl) ;
if (serializable && !forProxyClass) { if (serializable && !forProxyClass) {
/* Look for the writeObject method writeObjectMethod = bridge.writeObjectForSerialization(cl) ;
* Set the accessible flag on it here. ObjectOutputStream readObjectMethod = bridge.readObjectForSerialization(cl);
* will call it as necessary.
*/
writeObjectMethod = getPrivateMethod( cl, "writeObject",
new Class<?>[] { java.io.ObjectOutputStream.class }, Void.TYPE ) ;
readObjectMethod = getPrivateMethod( cl, "readObject",
new Class<?>[] { java.io.ObjectInputStream.class }, Void.TYPE ) ;
} }
return null; return null;
} }
@ -585,27 +596,6 @@ public class ObjectStreamClass implements java.io.Serializable {
} }
} }
/**
* Returns non-static private method with given signature defined by given
* class, or null if none found. Access checks are disabled on the
* returned method (if any).
*/
private static Method getPrivateMethod(Class<?> cl, String name,
Class<?>[] argTypes,
Class<?> returnType)
{
try {
Method meth = cl.getDeclaredMethod(name, argTypes);
meth.setAccessible(true);
int mods = meth.getModifiers();
return ((meth.getReturnType() == returnType) &&
((mods & Modifier.STATIC) == 0) &&
((mods & Modifier.PRIVATE) != 0)) ? meth : null;
} catch (NoSuchMethodException ex) {
return null;
}
}
// Specific to RMI-IIOP // Specific to RMI-IIOP
/** /**
* Java to IDL ptc-02-01-12 1.5.1 * Java to IDL ptc-02-01-12 1.5.1
@ -848,6 +838,22 @@ public class ObjectStreamClass implements java.io.Serializable {
return writeObjectMethod != null ; return writeObjectMethod != null ;
} }
/**
* Returns true if represented class is serializable or externalizable and
* defines a conformant writeReplace method. Otherwise, returns false.
*/
boolean hasWriteReplaceMethod() {
return (writeReplaceObjectMethod != null);
}
/**
* Returns true if represented class is serializable or externalizable and
* defines a conformant readResolve method. Otherwise, returns false.
*/
boolean hasReadResolveMethod() {
return (readResolveObjectMethod != null);
}
/** /**
* Returns when or not this class should be custom * Returns when or not this class should be custom
* marshaled (use chunking). This should happen if * marshaled (use chunking). This should happen if
@ -904,7 +910,7 @@ public class ObjectStreamClass implements java.io.Serializable {
{ {
if (cons != null) { if (cons != null) {
try { try {
return cons.newInstance(new Object[0]); return cons.newInstance();
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed // should not occur, as access checks have been suppressed
InternalError ie = new InternalError(); InternalError ie = new InternalError();
@ -912,7 +918,7 @@ public class ObjectStreamClass implements java.io.Serializable {
throw ie ; throw ie ;
} }
} else { } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException("no constructor for " + ofClass);
} }
} }
@ -921,15 +927,8 @@ public class ObjectStreamClass implements java.io.Serializable {
* Access checks are disabled on the returned constructor (if any), since * Access checks are disabled on the returned constructor (if any), since
* the defining class may still be non-public. * the defining class may still be non-public.
*/ */
private static Constructor getExternalizableConstructor(Class<?> cl) { private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
try { return bridge.newConstructorForExternalization(cl);
Constructor cons = cl.getDeclaredConstructor(new Class<?>[0]);
cons.setAccessible(true);
return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
cons : null;
} catch (NoSuchMethodException ex) {
return null;
}
} }
/** /**
@ -937,28 +936,8 @@ public class ObjectStreamClass implements java.io.Serializable {
* superclass, or null if none found. Access checks are disabled on the * superclass, or null if none found. Access checks are disabled on the
* returned constructor (if any). * returned constructor (if any).
*/ */
private static Constructor getSerializableConstructor(Class<?> cl) { private static Constructor<?> getSerializableConstructor(Class<?> cl) {
Class<?> initCl = cl; return bridge.newConstructorForSerialization(cl);
while (Serializable.class.isAssignableFrom(initCl)) {
if ((initCl = initCl.getSuperclass()) == null) {
return null;
}
}
try {
Constructor cons = initCl.getDeclaredConstructor(new Class<?>[0]);
int mods = cons.getModifiers();
if ((mods & Modifier.PRIVATE) != 0 ||
((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
!packageEquals(cl, initCl)))
{
return null;
}
cons = bridge.newConstructorForSerialization(cl, cons);
cons.setAccessible(true);
return cons;
} catch (NoSuchMethodException ex) {
return null;
}
} }
/* /*
@ -1522,11 +1501,11 @@ public class ObjectStreamClass implements java.io.Serializable {
* @since JDK 1.2 * @since JDK 1.2
*/ */
private boolean hasExternalizableBlockData; private boolean hasExternalizableBlockData;
Method writeObjectMethod; private transient MethodHandle writeObjectMethod;
Method readObjectMethod; private transient MethodHandle readObjectMethod;
private transient Method writeReplaceObjectMethod; private transient MethodHandle writeReplaceObjectMethod;
private transient Method readResolveObjectMethod; private transient MethodHandle readResolveObjectMethod;
private Constructor cons ; private transient Constructor<?> cons;
/** /**
* Beginning in Java to IDL ptc/02-01-12, RMI-IIOP has a * Beginning in Java to IDL ptc/02-01-12, RMI-IIOP has a
@ -1543,44 +1522,12 @@ public class ObjectStreamClass implements java.io.Serializable {
*/ */
private ObjectStreamClass localClassDesc; private ObjectStreamClass localClassDesc;
/* Find out if the class has a static class initializer <clinit> */
private static Method hasStaticInitializerMethod = null;
/** /**
* Returns true if the given class defines a static initializer method, * Returns true if the given class defines a static initializer method,
* false otherwise. * false otherwise.
*/ */
private static boolean hasStaticInitializer(Class<?> cl) { private static boolean hasStaticInitializer(Class<?> cl) {
if (hasStaticInitializerMethod == null) { return bridge.hasStaticInitializerForSerialization(cl);
Class<?> classWithThisMethod = null;
try {
if (classWithThisMethod == null)
classWithThisMethod = java.io.ObjectStreamClass.class;
hasStaticInitializerMethod =
classWithThisMethod.getDeclaredMethod("hasStaticInitializer",
new Class<?>[] { Class.class });
} catch (NoSuchMethodException ex) {
}
if (hasStaticInitializerMethod == null) {
// XXX I18N, logging needed
throw new InternalError("Can't find hasStaticInitializer method on "
+ classWithThisMethod.getName());
}
hasStaticInitializerMethod.setAccessible(true);
}
try {
Boolean retval = (Boolean)
hasStaticInitializerMethod.invoke(null, new Object[] { cl });
return retval.booleanValue();
} catch (Exception ex) {
// XXX I18N, logging needed
InternalError ie = new InternalError( "Error invoking hasStaticInitializer" ) ;
ie.initCause( ex ) ;
throw ie ;
}
} }
@ -1754,7 +1701,6 @@ public class ObjectStreamClass implements java.io.Serializable {
if ((meth == null) || (meth.getReturnType() != returnType)) { if ((meth == null) || (meth.getReturnType() != returnType)) {
return null; return null;
} }
meth.setAccessible(true);
int mods = meth.getModifiers(); int mods = meth.getModifiers();
if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) { if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
return null; return null;

View File

@ -32,6 +32,7 @@ module java.corba {
requires java.logging; requires java.logging;
requires java.naming; requires java.naming;
requires java.transaction; requires java.transaction;
requires jdk.unsupported;
exports javax.activity; exports javax.activity;
exports javax.rmi; exports javax.rmi;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,25 +25,24 @@
package sun.corba ; package sun.corba ;
import java.io.OptionalDataException;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field ; import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
import java.lang.reflect.Constructor ; import java.lang.reflect.Constructor ;
import java.lang.reflect.InvocationTargetException ;
import java.io.ObjectInputStream ;
import java.security.AccessController; import java.security.AccessController;
import java.security.Permission; import java.security.Permission;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import jdk.internal.misc.Unsafe ; import sun.misc.Unsafe;
import jdk.internal.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
/** This class provides the methods for fundamental JVM operations /** This class provides the methods for fundamental JVM operations
* needed in the ORB that are not part of the public Java API. This includes: * needed in the ORB that are not part of the public Java API. This includes:
* <ul> * <ul>
* <li>throwException, which can throw undeclared checked exceptions. * <li>throwException, which can throw undeclared checked exceptions.
* This is needed to handle throwing arbitrary exceptions across a standardized OMG interface that (incorrectly) does not specify appropriate exceptions.</li> * This is needed to handle throwing arbitrary exceptions across a standardized
* OMG interface that (incorrectly) does not specify appropriate exceptions.</li>
* <li>putXXX/getXXX methods that allow unchecked access to fields of objects. * <li>putXXX/getXXX methods that allow unchecked access to fields of objects.
* This is used for setting uninitialzed non-static final fields (which is * This is used for setting uninitialzed non-static final fields (which is
* impossible with reflection) and for speed.</li> * impossible with reflection) and for speed.</li>
@ -71,88 +70,28 @@ import jdk.internal.reflect.ReflectionFactory;
*/ */
public final class Bridge public final class Bridge
{ {
private static final Class[] NO_ARGS = new Class[] {};
private static final Permission getBridgePermission = private static final Permission getBridgePermission =
new BridgePermission( "getBridge" ) ; new BridgePermission("getBridge");
private static Bridge bridge = null ; private static Bridge bridge = null ;
// latestUserDefinedLoader() is a private static method /** Access to Unsafe to read/write fields. */
// in ObjectInputStream in JDK 1.3 through 1.5. private static final Unsafe unsafe = AccessController.doPrivileged(
// We use reflection in a doPrivileged block to get a (PrivilegedAction<Unsafe>)() -> {
// Method reference and make it accessible. try {
private final Method latestUserDefinedLoaderMethod ; Field field = Unsafe.class.getDeclaredField("theUnsafe");
private final Unsafe unsafe ; field.setAccessible(true);
return (Unsafe)field.get(null);
} catch (NoSuchFieldException |IllegalAccessException ex) {
throw new InternalError("Unsafe.theUnsafe field not available", ex);
}
}
) ;
private final ReflectionFactory reflectionFactory ; private final ReflectionFactory reflectionFactory ;
private Method getLatestUserDefinedLoaderMethod() private Bridge() {
{ reflectionFactory = ReflectionFactory.getReflectionFactory();
return (Method) AccessController.doPrivileged(
new PrivilegedAction()
{
public Object run()
{
Method result = null;
try {
Class io = ObjectInputStream.class;
result = io.getDeclaredMethod(
"latestUserDefinedLoader", NO_ARGS);
result.setAccessible(true);
} catch (NoSuchMethodException nsme) {
Error err = new Error( "java.io.ObjectInputStream" +
" latestUserDefinedLoader " + nsme );
err.initCause(nsme) ;
throw err ;
}
return result;
}
}
);
}
private Unsafe getUnsafe() {
Field fld = (Field)AccessController.doPrivileged(
new PrivilegedAction()
{
public Object run()
{
Field fld = null ;
try {
Class unsafeClass = jdk.internal.misc.Unsafe.class ;
fld = unsafeClass.getDeclaredField( "theUnsafe" ) ;
fld.setAccessible( true ) ;
return fld ;
} catch (NoSuchFieldException exc) {
Error err = new Error( "Could not access Unsafe" ) ;
err.initCause( exc ) ;
throw err ;
}
}
}
) ;
Unsafe unsafe = null;
try {
unsafe = (Unsafe)(fld.get( null )) ;
} catch (Throwable t) {
Error err = new Error( "Could not access Unsafe" ) ;
err.initCause( t ) ;
throw err ;
}
return unsafe ;
}
private Bridge()
{
latestUserDefinedLoaderMethod = getLatestUserDefinedLoaderMethod();
unsafe = getUnsafe() ;
reflectionFactory = (ReflectionFactory)AccessController.doPrivileged(
new ReflectionFactory.GetReflectionFactoryAction());
} }
/** Fetch the Bridge singleton. This requires the following /** Fetch the Bridge singleton. This requires the following
@ -182,23 +121,8 @@ public final class Bridge
/** Obtain the latest user defined ClassLoader from the call stack. /** Obtain the latest user defined ClassLoader from the call stack.
* This is required by the RMI-IIOP specification. * This is required by the RMI-IIOP specification.
*/ */
public final ClassLoader getLatestUserDefinedLoader() public final ClassLoader getLatestUserDefinedLoader() {
{ return jdk.internal.misc.VM.latestUserDefinedLoader();
try {
// Invoke the ObjectInputStream.latestUserDefinedLoader method
return (ClassLoader)latestUserDefinedLoaderMethod.invoke(null,
(Object[])NO_ARGS);
} catch (InvocationTargetException ite) {
Error err = new Error(
"sun.corba.Bridge.latestUserDefinedLoader: " + ite ) ;
err.initCause( ite ) ;
throw err ;
} catch (IllegalAccessException iae) {
Error err = new Error(
"sun.corba.Bridge.latestUserDefinedLoader: " + iae ) ;
err.initCause( iae ) ;
throw err ;
}
} }
/** /**
@ -345,6 +269,23 @@ public final class Bridge
return unsafe.objectFieldOffset( f ) ; return unsafe.objectFieldOffset( f ) ;
} }
/**
* Returns the offset of a static field.
*/
public final long staticFieldOffset(Field f)
{
return unsafe.staticFieldOffset( f ) ;
}
/**
* Ensure that the class has been initalized.
* @param cl the class to ensure is initialized
*/
public final void ensureClassInitialized(Class<?> cl) {
unsafe.ensureClassInitialized(cl);
}
/** Throw the exception. /** Throw the exception.
* The exception may be an undeclared checked exception. * The exception may be an undeclared checked exception.
*/ */
@ -353,16 +294,55 @@ public final class Bridge
unsafe.throwException( ee ) ; unsafe.throwException( ee ) ;
} }
/** Obtain a constructor for Class cl using constructor cons which /**
* may be the constructor defined in a superclass of cl. This is * Obtain a constructor for Class cl.
* used to create a constructor for Serializable classes that * This is used to create a constructor for Serializable classes that
* constructs an instance of the Serializable class using the * construct an instance of the Serializable class using the
* no args constructor of the first non-Serializable superclass * no args constructor of the first non-Serializable superclass
* of the Serializable class. * of the Serializable class.
*/ */
public final Constructor newConstructorForSerialization( Class cl, public final Constructor<?> newConstructorForSerialization( Class<?> cl ) {
Constructor cons ) return reflectionFactory.newConstructorForSerialization( cl ) ;
{
return reflectionFactory.newConstructorForSerialization( cl, cons ) ;
} }
public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
return reflectionFactory.newConstructorForExternalization( cl ) ;
}
/**
* Returns true if the given class defines a static initializer method,
* false otherwise.
*/
public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
return reflectionFactory.hasStaticInitializerForSerialization(cl);
}
public final MethodHandle writeObjectForSerialization(Class<?> cl) {
return reflectionFactory.writeObjectForSerialization(cl);
}
public final MethodHandle readObjectForSerialization(Class<?> cl) {
return reflectionFactory.readObjectForSerialization(cl);
}
public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
return reflectionFactory.readObjectNoDataForSerialization(cl);
}
public final MethodHandle readResolveForSerialization(Class<?> cl) {
return reflectionFactory.readResolveForSerialization(cl);
}
public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
return reflectionFactory.writeReplaceForSerialization(cl);
}
/**
* Return a new OptionalDataException instance.
* @return a new OptionalDataException instance
*/
public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
return reflectionFactory.newOptionalDataExceptionForSerialization(bool);
}
} }

View File

@ -25,13 +25,13 @@
package sun.corba; package sun.corba;
import com.sun.corba.se.impl.io.ValueUtility;
import jdk.internal.misc.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import com.sun.corba.se.impl.io.ValueUtility;
import sun.misc.Unsafe;
/** A repository of "shared secrets", which are a mechanism for /** A repository of "shared secrets", which are a mechanism for
calling implementation-private methods in another package without calling implementation-private methods in another package without
using reflection. A package-private class implements a public using reflection. A package-private class implements a public
@ -43,22 +43,22 @@ import java.security.PrivilegedAction;
// SharedSecrets cloned in corba repo to avoid build issues // SharedSecrets cloned in corba repo to avoid build issues
public class SharedSecrets { public class SharedSecrets {
private static final Unsafe unsafe = getUnsafe();
private static JavaCorbaAccess javaCorbaAccess;
private static Unsafe getUnsafe() { /** Access to Unsafe to read/write fields. */
PrivilegedAction<Unsafe> pa = () -> { private static final Unsafe unsafe = AccessController.doPrivileged(
Class<?> unsafeClass = jdk.internal.misc.Unsafe.class ; (PrivilegedAction<Unsafe>)() -> {
try { try {
Field f = unsafeClass.getDeclaredField("theUnsafe"); Field field = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true); field.setAccessible(true);
return (Unsafe) f.get(null); return (Unsafe)field.get(null);
} catch (Exception e) {
throw new Error(e); } catch (NoSuchFieldException |IllegalAccessException ex) {
} throw new InternalError("Unsafe.theUnsafe field not available", ex);
}; }
return AccessController.doPrivileged(pa); }
} );
private static JavaCorbaAccess javaCorbaAccess;
public static JavaCorbaAccess getJavaCorbaAccess() { public static JavaCorbaAccess getJavaCorbaAccess() {
if (javaCorbaAccess == null) { if (javaCorbaAccess == null) {