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;
import java.io.InputStream;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.io.ObjectInputValidation;
import java.io.NotActiveException;
import java.io.InvalidObjectException;
import java.io.InvalidClassException;
import java.io.DataInputStream;
import java.io.OptionalDataException;
import java.io.WriteAbortedException;
import java.io.Externalizable;
import java.io.EOFException;
import java.lang.reflect.*;
import java.util.Vector;
import java.util.Stack;
import java.util.Hashtable;
import java.util.Enumeration;
import sun.corba.Bridge ;
@ -54,7 +49,6 @@ import sun.corba.Bridge ;
import java.security.AccessController ;
import java.security.PrivilegedAction ;
import com.sun.corba.se.impl.io.ObjectStreamClass;
import com.sun.corba.se.impl.util.Utility;
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.SendingContext.CodeBase;
import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandler;
import java.security.*;
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.UtilSystemException ;
@ -182,75 +174,6 @@ public class IIOPInputStream
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
// to deserialize an object
protected byte getStreamFormatVersion() {
@ -395,7 +318,6 @@ public class IIOPInputStream
int offset)
/* throws OptionalDataException, ClassNotFoundException, IOException */
{
/* Save the current state and get ready to read an object. */
Object prevObject = currentObject;
ObjectStreamClass prevClassDesc = currentClassDesc;
@ -947,7 +869,7 @@ public class IIOPInputStream
if (!objectRead)
result = new EOFException("No more optional data");
else
result = createOptionalDataException();
result = bridge.newOptionalDataExceptionForSerialization(true);
result.initCause(marshalException);
@ -1230,8 +1152,7 @@ public class IIOPInputStream
readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject,
(currentClassDesc.readObjectMethod
!= null));
currentClassDesc.hasReadObject());
} else {
if (currentClassDesc.hasReadObject())
setState(IN_READ_OBJECT_REMOTE_NOT_CUSTOM_MARSHALED);
@ -1556,8 +1477,7 @@ public class IIOPInputStream
readObjectState.beginUnmarshalCustomValue(this,
calledDefaultWriteObject,
(currentClassDesc.readObjectMethod
!= null));
currentClassDesc.hasReadObject());
}
boolean usedReadObject = false;
@ -1714,13 +1634,8 @@ public class IIOPInputStream
throws InvalidClassException, StreamCorruptedException,
ClassNotFoundException, IOException
{
if (osc.readObjectMethod == null) {
return false;
}
try {
osc.readObjectMethod.invoke( obj, readObjectArgList ) ;
return true;
return osc.invokeReadObject( obj, this ) ;
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof ClassNotFoundException)
@ -1734,8 +1649,6 @@ public class IIOPInputStream
else
// XXX I18N, logging needed.
throw new Error("internal error");
} catch (IllegalAccessException e) {
return false;
}
}

View File

@ -31,33 +31,23 @@
package com.sun.corba.se.impl.io;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.portable.OutputStream;
import java.security.AccessController ;
import java.security.PrivilegedAction ;
import java.io.IOException;
import java.io.DataOutputStream;
import java.io.Serializable;
import java.io.InvalidClassException;
import java.io.StreamCorruptedException;
import java.io.Externalizable;
import java.io.ObjectStreamException;
import java.io.NotSerializableException;
import java.io.NotActiveException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import java.util.Stack;
import javax.rmi.CORBA.Util;
import javax.rmi.CORBA.ValueHandlerMultiFormat;
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.RepositoryId;
@ -621,7 +611,7 @@ public class IIOPOutputStream
writeObjectState.enterWriteObject(this);
// writeObject(obj, c, this);
osc.writeObjectMethod.invoke( obj, writeObjectArgList ) ;
osc.invokeWriteObject( obj, this ) ;
writeObjectState.exitWriteObject(this);
@ -636,8 +626,6 @@ public class IIOPOutputStream
else
// XXX I18N, Logging needed.
throw new Error("invokeObjectWriter internal error",e);
} catch (IllegalAccessException e) {
// cannot happen
}
}
@ -761,60 +749,53 @@ public class IIOPOutputStream
*/
private void outputClassFields(Object o, Class cl,
ObjectStreamField[] fields)
throws IOException, InvalidClassException {
throws IOException {
for (int i = 0; i < fields.length; i++) {
if (fields[i].getField() == null)
// XXX I18N, Logging needed.
throw new InvalidClassException(cl.getName(),
"Nonexistent field " + fields[i].getName());
try {
switch (fields[i].getTypeCode()) {
case 'B':
byte byteValue = fields[i].getField().getByte( o ) ;
byte byteValue = bridge.getByte(o, fields[i].getFieldID()) ;
orbStream.write_octet(byteValue);
break;
case 'C':
char charValue = fields[i].getField().getChar( o ) ;
char charValue = bridge.getChar(o, fields[i].getFieldID()) ;
orbStream.write_wchar(charValue);
break;
case 'F':
float floatValue = fields[i].getField().getFloat( o ) ;
float floatValue = bridge.getFloat(o, fields[i].getFieldID()) ;
orbStream.write_float(floatValue);
break;
case 'D' :
double doubleValue = fields[i].getField().getDouble( o ) ;
double doubleValue = bridge.getDouble(o, fields[i].getFieldID()) ;
orbStream.write_double(doubleValue);
break;
case 'I':
int intValue = fields[i].getField().getInt( o ) ;
int intValue = bridge.getInt(o, fields[i].getFieldID()) ;
orbStream.write_long(intValue);
break;
case 'J':
long longValue = fields[i].getField().getLong( o ) ;
long longValue = bridge.getLong(o, fields[i].getFieldID()) ;
orbStream.write_longlong(longValue);
break;
case 'S':
short shortValue = fields[i].getField().getShort( o ) ;
short shortValue = bridge.getShort(o, fields[i].getFieldID()) ;
orbStream.write_short(shortValue);
break;
case 'Z':
boolean booleanValue = fields[i].getField().getBoolean( o ) ;
boolean booleanValue = bridge.getBoolean(o, fields[i].getFieldID()) ;
orbStream.write_boolean(booleanValue);
break;
case '[':
case 'L':
Object objectValue = fields[i].getField().get( o ) ;
Object objectValue = bridge.getObject(o, fields[i].getFieldID()) ;
writeObjectField(fields[i], objectValue);
break;
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;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.invoke.MethodHandle;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.DigestOutputStream;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedAction;
import java.lang.reflect.Modifier;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@ -80,9 +80,6 @@ public class ObjectStreamClass implements java.io.Serializable {
public static final long kDefaultUID = -1;
private static Object noArgsList[] = {};
private static Class<?> noTypesList[] = {};
/** true if represents enum type */
private boolean isEnum;
@ -311,12 +308,37 @@ public class ObjectStreamClass implements java.io.Serializable {
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) {
if (writeReplaceObjectMethod != null) {
try {
return (Serializable) writeReplaceObjectMethod.invoke(value,noArgsList);
return (Serializable) writeReplaceObjectMethod.invoke(value);
} catch (Throwable t) {
throw new RuntimeException(t);
throw new InternalError("unexpected error", t);
}
}
else return value;
@ -325,9 +347,9 @@ public class ObjectStreamClass implements java.io.Serializable {
public Object readResolve(Object value) {
if (readResolveObjectMethod != null) {
try {
return readResolveObjectMethod.invoke(value,noArgsList);
return readResolveObjectMethod.invoke(value);
} catch (Throwable t) {
throw new RuntimeException(t);
throw new InternalError("unexpected error", t);
}
}
else return value;
@ -382,29 +404,32 @@ public class ObjectStreamClass implements java.io.Serializable {
*/
}
private static final class PersistentFieldsValue
static final class PersistentFieldsValue
extends ClassValue<ObjectStreamField[]> {
PersistentFieldsValue() { }
protected ObjectStreamField[] computeValue(Class<?> type) {
try {
bridge.ensureClassInitialized(type);
Field pf = type.getDeclaredField("serialPersistentFields");
int mods = pf.getModifiers();
if (Modifier.isPrivate(mods) && Modifier.isStatic(mods) &&
Modifier.isFinal(mods)) {
pf.setAccessible(true);
long offset = bridge.staticFieldOffset(pf);
java.io.ObjectStreamField[] fields =
(java.io.ObjectStreamField[])pf.get(type);
(java.io.ObjectStreamField[])bridge.getObject(type, offset);
return translateFields(fields);
}
} catch (NoSuchFieldException | IllegalAccessException |
} catch (NoSuchFieldException |
IllegalArgumentException | ClassCastException e) {
}
return null;
}
private static ObjectStreamField[] translateFields(
java.io.ObjectStreamField[] fields) {
private static ObjectStreamField[] translateFields(java.io.ObjectStreamField[] fields) {
if (fields == null) {
return null;
}
ObjectStreamField[] translation =
new ObjectStreamField[fields.length];
for (int i = 0; i < fields.length; i++) {
@ -453,10 +478,8 @@ public class ObjectStreamClass implements java.io.Serializable {
fields = persistentFieldsValue.get(cl);
if (fields == null) {
/* Get all of the declared fields for this
* Class. setAccessible on all fields so they
* can be accessed later. Create a temporary
* ObjectStreamField array to hold each
/* Get all of the declared fields for this Class.
* Create a temporary ObjectStreamField array to hold each
* non-static, non-transient field. Then copy the
* temporary array into an array of the correct
* size once the number of fields is known.
@ -471,7 +494,6 @@ public class ObjectStreamClass implements java.io.Serializable {
int modifiers = fld.getModifiers();
if (!Modifier.isStatic(modifiers) &&
!Modifier.isTransient(modifiers)) {
fld.setAccessible(true) ;
tempFields[numFields++] = new ObjectStreamField(fld);
}
}
@ -487,7 +509,6 @@ public class ObjectStreamClass implements java.io.Serializable {
try {
Field reflField = cl.getDeclaredField(fields[j].getName());
if (fields[j].getType() == reflField.getType()) {
reflField.setAccessible(true);
fields[j].setField(reflField);
}
} catch (NoSuchFieldException e) {
@ -527,8 +548,8 @@ public class ObjectStreamClass implements java.io.Serializable {
int mods = f.getModifiers();
// SerialBug 5: static final SUID should be read
if (Modifier.isStatic(mods) && Modifier.isFinal(mods) ) {
f.setAccessible(true);
suid = f.getLong(cl);
long offset = bridge.staticFieldOffset(f);
suid = bridge.getLong(cl, offset);
// SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl);
} else {
@ -540,16 +561,12 @@ public class ObjectStreamClass implements java.io.Serializable {
suid = _computeSerialVersionUID(cl);
// SerialBug 2: should be computed after writeObject
// actualSuid = computeStructuralUID(cl);
} catch (IllegalAccessException ex) {
suid = _computeSerialVersionUID(cl);
}
}
writeReplaceObjectMethod = ObjectStreamClass.getInheritableMethod(cl,
"writeReplace", noTypesList, Object.class);
writeReplaceObjectMethod = bridge.writeReplaceForSerialization(cl);
readResolveObjectMethod = ObjectStreamClass.getInheritableMethod(cl,
"readResolve", noTypesList, Object.class);
readResolveObjectMethod = bridge.readResolveForSerialization(cl);
if (externalizable)
cons = getExternalizableConstructor(cl) ;
@ -557,14 +574,8 @@ public class ObjectStreamClass implements java.io.Serializable {
cons = getSerializableConstructor(cl) ;
if (serializable && !forProxyClass) {
/* Look for the writeObject method
* Set the accessible flag on it here. ObjectOutputStream
* 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 ) ;
writeObjectMethod = bridge.writeObjectForSerialization(cl) ;
readObjectMethod = bridge.readObjectForSerialization(cl);
}
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
/**
* Java to IDL ptc-02-01-12 1.5.1
@ -848,6 +838,22 @@ public class ObjectStreamClass implements java.io.Serializable {
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
* marshaled (use chunking). This should happen if
@ -904,7 +910,7 @@ public class ObjectStreamClass implements java.io.Serializable {
{
if (cons != null) {
try {
return cons.newInstance(new Object[0]);
return cons.newInstance();
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
InternalError ie = new InternalError();
@ -912,7 +918,7 @@ public class ObjectStreamClass implements java.io.Serializable {
throw ie ;
}
} 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
* the defining class may still be non-public.
*/
private static Constructor getExternalizableConstructor(Class<?> cl) {
try {
Constructor cons = cl.getDeclaredConstructor(new Class<?>[0]);
cons.setAccessible(true);
return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
cons : null;
} catch (NoSuchMethodException ex) {
return null;
}
private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
return bridge.newConstructorForExternalization(cl);
}
/**
@ -937,28 +936,8 @@ public class ObjectStreamClass implements java.io.Serializable {
* superclass, or null if none found. Access checks are disabled on the
* returned constructor (if any).
*/
private static Constructor getSerializableConstructor(Class<?> cl) {
Class<?> initCl = 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;
}
private static Constructor<?> getSerializableConstructor(Class<?> cl) {
return bridge.newConstructorForSerialization(cl);
}
/*
@ -1522,11 +1501,11 @@ public class ObjectStreamClass implements java.io.Serializable {
* @since JDK 1.2
*/
private boolean hasExternalizableBlockData;
Method writeObjectMethod;
Method readObjectMethod;
private transient Method writeReplaceObjectMethod;
private transient Method readResolveObjectMethod;
private Constructor cons ;
private transient MethodHandle writeObjectMethod;
private transient MethodHandle readObjectMethod;
private transient MethodHandle writeReplaceObjectMethod;
private transient MethodHandle readResolveObjectMethod;
private transient Constructor<?> cons;
/**
* 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;
/* 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,
* false otherwise.
*/
private static boolean hasStaticInitializer(Class<?> cl) {
if (hasStaticInitializerMethod == null) {
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 ;
}
return bridge.hasStaticInitializerForSerialization(cl);
}
@ -1754,7 +1701,6 @@ public class ObjectStreamClass implements java.io.Serializable {
if ((meth == null) || (meth.getReturnType() != returnType)) {
return null;
}
meth.setAccessible(true);
int mods = meth.getModifiers();
if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
return null;

View File

@ -32,6 +32,7 @@ module java.corba {
requires java.logging;
requires java.naming;
requires java.transaction;
requires jdk.unsupported;
exports javax.activity;
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,25 +25,24 @@
package sun.corba ;
import java.io.OptionalDataException;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Field ;
import java.lang.reflect.Method ;
import java.lang.reflect.Constructor ;
import java.lang.reflect.InvocationTargetException ;
import java.io.ObjectInputStream ;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import jdk.internal.misc.Unsafe ;
import jdk.internal.reflect.ReflectionFactory;
import sun.misc.Unsafe;
import sun.reflect.ReflectionFactory;
/** This class provides the methods for fundamental JVM operations
* needed in the ORB that are not part of the public Java API. This includes:
* <ul>
* <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.
* This is used for setting uninitialzed non-static final fields (which is
* impossible with reflection) and for speed.</li>
@ -71,88 +70,28 @@ import jdk.internal.reflect.ReflectionFactory;
*/
public final class Bridge
{
private static final Class[] NO_ARGS = new Class[] {};
private static final Permission getBridgePermission =
new BridgePermission("getBridge");
private static Bridge bridge = null ;
// latestUserDefinedLoader() is a private static method
// in ObjectInputStream in JDK 1.3 through 1.5.
// We use reflection in a doPrivileged block to get a
// Method reference and make it accessible.
private final Method latestUserDefinedLoaderMethod ;
private final Unsafe unsafe ;
/** Access to Unsafe to read/write fields. */
private static final Unsafe unsafe = AccessController.doPrivileged(
(PrivilegedAction<Unsafe>)() -> {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
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 Method getLatestUserDefinedLoaderMethod()
{
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());
private Bridge() {
reflectionFactory = ReflectionFactory.getReflectionFactory();
}
/** 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.
* This is required by the RMI-IIOP specification.
*/
public final ClassLoader getLatestUserDefinedLoader()
{
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 ;
}
public final ClassLoader getLatestUserDefinedLoader() {
return jdk.internal.misc.VM.latestUserDefinedLoader();
}
/**
@ -345,6 +269,23 @@ public final class Bridge
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.
* The exception may be an undeclared checked exception.
*/
@ -353,16 +294,55 @@ public final class Bridge
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
* used to create a constructor for Serializable classes that
* constructs an instance of the Serializable class using the
/**
* Obtain a constructor for Class cl.
* This is used to create a constructor for Serializable classes that
* construct an instance of the Serializable class using the
* no args constructor of the first non-Serializable superclass
* of the Serializable class.
*/
public final Constructor newConstructorForSerialization( Class cl,
Constructor cons )
{
return reflectionFactory.newConstructorForSerialization( cl, cons ) ;
public final Constructor<?> newConstructorForSerialization( Class<?> cl ) {
return reflectionFactory.newConstructorForSerialization( cl ) ;
}
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;
import com.sun.corba.se.impl.io.ValueUtility;
import jdk.internal.misc.Unsafe;
import java.lang.reflect.Field;
import java.security.AccessController;
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
calling implementation-private methods in another package without
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
public class SharedSecrets {
private static final Unsafe unsafe = getUnsafe();
private static JavaCorbaAccess javaCorbaAccess;
private static Unsafe getUnsafe() {
PrivilegedAction<Unsafe> pa = () -> {
Class<?> unsafeClass = jdk.internal.misc.Unsafe.class ;
/** Access to Unsafe to read/write fields. */
private static final Unsafe unsafe = AccessController.doPrivileged(
(PrivilegedAction<Unsafe>)() -> {
try {
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
} catch (Exception e) {
throw new Error(e);
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe)field.get(null);
} 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() {
if (javaCorbaAccess == null) {