Skip to content

Commit

Permalink
8278065: Refactor subclassAudits to use ClassValue
Browse files Browse the repository at this point in the history
Reviewed-by: rriggs, plevart
  • Loading branch information
rkennke committed Jan 12, 2022
1 parent f54ce84 commit 8fed8ab
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 103 deletions.
27 changes: 8 additions & 19 deletions src/java.base/share/classes/java/io/ObjectInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@
package java.io;

import java.io.ObjectInputFilter.Config;
import java.io.ObjectStreamClass.WeakClassKey;
import java.io.ObjectStreamClass.RecordSupport;
import java.lang.System.Logger;
import java.lang.invoke.MethodHandle;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Modifier;
Expand All @@ -43,10 +41,6 @@
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static java.io.ObjectStreamClass.processQueue;

import jdk.internal.access.SharedSecrets;
import jdk.internal.event.DeserializationEvent;
Expand Down Expand Up @@ -282,12 +276,13 @@ public class ObjectInputStream

private static class Caches {
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
new ConcurrentHashMap<>();

/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
static final ClassValue<Boolean> subclassAudits =
new ClassValue<>() {
@Override
protected Boolean computeValue(Class<?> type) {
return auditSubclass(type);
}
};

/**
* Property to permit setting a filter after objects
Expand Down Expand Up @@ -1638,13 +1633,7 @@ private void verifySubclass() {
if (sm == null) {
return;
}
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = auditSubclass(cl);
Caches.subclassAudits.putIfAbsent(key, result);
}
boolean result = Caches.subclassAudits.get(cl);
if (!result) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
Expand Down
26 changes: 8 additions & 18 deletions src/java.base/share/classes/java/io/ObjectOutputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,13 @@

package java.io;

import java.io.ObjectStreamClass.WeakClassKey;
import java.lang.ref.ReferenceQueue;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
import sun.reflect.misc.ReflectUtil;

/**
Expand Down Expand Up @@ -177,12 +172,13 @@ public class ObjectOutputStream

private static class Caches {
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
new ConcurrentHashMap<>();

/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
static final ClassValue<Boolean> subclassAudits =
new ClassValue<>() {
@Override
protected Boolean computeValue(Class<?> type) {
return auditSubclass(type);
}
};
}

/** filter stream for handling block data conversion */
Expand Down Expand Up @@ -1065,13 +1061,7 @@ private void verifySubclass() {
if (sm == null) {
return;
}
processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = auditSubclass(cl);
Caches.subclassAudits.putIfAbsent(key, result);
}
boolean result = Caches.subclassAudits.get(cl);
if (!result) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
Expand Down
66 changes: 0 additions & 66 deletions src/java.base/share/classes/java/io/ObjectStreamClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
Expand Down Expand Up @@ -58,7 +55,6 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import jdk.internal.misc.Unsafe;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
Expand Down Expand Up @@ -2227,68 +2223,6 @@ private static ObjectStreamField[] matchFields(ObjectStreamField[] fields,
return matches;
}

/**
* Removes from the specified map any keys that have been enqueued
* on the specified reference queue.
*/
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map)
{
Reference<? extends Class<?>> ref;
while((ref = queue.poll()) != null) {
map.remove(ref);
}
}

/**
* Weak key for Class objects.
*
**/
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;

/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}

/**
* Returns the identity hash code of the original referent.
*/
public int hashCode() {
return hash;
}

/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}

if (obj instanceof WeakClassKey) {
Class<?> referent = get();
return (referent != null) &&
(((WeakClassKey) obj).refersTo(referent));
} else {
return false;
}
}
}

/**
* A LRA cache of record deserialization constructors.
*/
Expand Down

1 comment on commit 8fed8ab

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.