Skip to content

Commit

Permalink
ClassValueCompat to support systems without java.lang.ClassValue
Browse files Browse the repository at this point in the history
  • Loading branch information
nwk37011 committed Sep 17, 2021
1 parent 7d7daa6 commit 272907f
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 7 deletions.
9 changes: 9 additions & 0 deletions project/MimaFilters.scala
Expand Up @@ -78,6 +78,15 @@ object MimaFilters extends AutoPlugin {

// #9741
ProblemFilters.exclude[MissingClassProblem]("scala.collection.immutable.SeqMap$SeqMapBuilderImpl"), // private[SeqMap]

// #9752
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.ClassTag$cache$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.runtime.JavaMirrors$JavaMirror$typeTagCache$"),
ProblemFilters.exclude[MissingTypesProblem]("scala.reflect.runtime.JavaMirrors$JavaMirror$typeTagCache$"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$ClassValueInterface"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$JavaClassValue"),
ProblemFilters.exclude[MissingClassProblem]("scala.compat.ClassValueCompat$FallbackClassValue"),
)

override val buildSettings = Seq(
Expand Down
47 changes: 47 additions & 0 deletions src/library/scala/compat/ClassValueCompat.scala
@@ -0,0 +1,47 @@
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package scala.compat

import scala.util.Try

private[scala] abstract class ClassValueCompat[T] {

private def checkClassValueAvailability(): Boolean = Try {
Class.forName("java.lang.ClassValue", false, getClass.getClassLoader)
true
}.getOrElse(false)

private val instance = if (checkClassValueAvailability()) new JavaClassValue() else new FallbackClassValue()

private class JavaClassValue extends ClassValue[T] with ClassValueInterface {
override def computeValue(`type`: Class[_]): T = ClassValueCompat.this.computeValue(`type`)
}

private class FallbackClassValue extends ClassValueInterface {
override def get(param1Class: Class[_]): T = ClassValueCompat.this.get(param1Class)

override def remove(param1Class: Class[_]): Unit = {}
}

private trait ClassValueInterface {
def get(param1Class: Class[_]): T
def remove(param1Class: Class[_]): Unit
}

def get(`type`: Class[_]): T = instance.get(`type`)

def remove(`type`: Class[_]): Unit = instance.remove(`type`)

protected def computeValue(`type`: Class[_]): T

}
4 changes: 2 additions & 2 deletions src/library/scala/reflect/ClassTag.scala
Expand Up @@ -15,8 +15,8 @@ package reflect

import java.lang.{Class => jClass}
import java.lang.ref.{WeakReference => jWeakReference}

import scala.annotation.{implicitNotFound, nowarn}
import scala.compat.ClassValueCompat

/**
*
Expand Down Expand Up @@ -116,7 +116,7 @@ object ClassTag {
val Null : ClassTag[scala.Null] = Manifest.Null

private val cacheDisabled = java.lang.Boolean.getBoolean("scala.reflect.classtag.cache.disable")
private[this] object cache extends ClassValue[jWeakReference[ClassTag[_]]] {
private[this] object cache extends ClassValueCompat[jWeakReference[ClassTag[_]]] {
override def computeValue(runtimeClass: jClass[_]): jWeakReference[ClassTag[_]] =
new jWeakReference(computeTag(runtimeClass))

Expand Down
56 changes: 53 additions & 3 deletions src/library/scala/runtime/ModuleSerializationProxy.java
Expand Up @@ -15,14 +15,12 @@
import java.io.Serializable;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashSet;
import java.util.Set;

/** A serialization proxy for singleton objects */
public final class ModuleSerializationProxy implements Serializable {
private static final long serialVersionUID = 1L;
private final Class<?> moduleClass;
private static final ClassValue<Object> instances = new ClassValue<Object>() {
private static final ClassValueCompat<Object> instances = new ClassValueCompat<Object>() {
@Override
@SuppressWarnings("removal") // JDK 17 deprecates AccessController
protected Object computeValue(Class<?> type) {
Expand All @@ -48,4 +46,56 @@ public ModuleSerializationProxy(Class<?> moduleClass) {
private Object readResolve() {
return instances.get(moduleClass);
}

private static boolean checkClassValueAvailability() {
try {
Class.forName("java.lang.ClassValue", false, Object.class.getClassLoader());
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

private interface ClassValueInterface<T> {
T get(Class<?> param1Class);

void remove(Class<?> param1Class);
}

private abstract static class ClassValueCompat<T> {

private final ClassValueInterface<T> instance;

protected ClassValueCompat() {
instance = checkClassValueAvailability() ? new JavaClassValue() : new FallbackClassValue();
}

private class JavaClassValue extends ClassValue<T> implements ClassValueInterface<T> {
@Override
protected T computeValue(Class<?> aClass) {
return ClassValueCompat.this.computeValue(aClass);
}
}

private class FallbackClassValue implements ClassValueInterface<T> {
@Override
public T get(Class<?> type) {
return ClassValueCompat.this.computeValue(type);
}

@Override
public void remove(Class<?> type) {}
}

protected abstract T computeValue(Class<?> type);

public T get(Class<?> type) {
return instance.get(type);
}

public void remove(Class<?> type) {
instance.remove(type);
}

}
}
3 changes: 2 additions & 1 deletion src/reflect/scala/reflect/macros/Attachments.scala
Expand Up @@ -15,6 +15,7 @@ package reflect
package macros

import reflect.internal.util.Position
import scala.compat.ClassValueCompat

/**
* <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
Expand Down Expand Up @@ -109,7 +110,7 @@ abstract class Attachments { self =>
}

private object Attachments {
private val matchesTagCache = new ClassValue[Function1[Any, Boolean]] {
private val matchesTagCache = new ClassValueCompat[Function1[Any, Boolean]] {
override def computeValue(cls: Class[_]): Function[Any, Boolean] = cls.isInstance(_)
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/reflect/scala/reflect/runtime/JavaMirrors.scala
Expand Up @@ -37,6 +37,7 @@ import scala.collection.mutable.ListBuffer
import internal.Flags._
import ReflectionUtils._
import scala.annotation.nowarn
import scala.compat.ClassValueCompat
import scala.reflect.api.TypeCreator
import scala.runtime.{ BoxesRunTime, ScalaRunTime }

Expand Down Expand Up @@ -120,7 +121,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
private[this] val fieldCache = new TwoWayCache[jField, TermSymbol]
private[this] val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]

private[this] object typeTagCache extends ClassValue[jWeakReference[TypeTag[_]]]() {
private[this] object typeTagCache extends ClassValueCompat[jWeakReference[TypeTag[_]]]() {
val typeCreator = new ThreadLocal[TypeCreator]()

override protected def computeValue(cls: jClass[_]): jWeakReference[TypeTag[_]] = {
Expand Down

0 comments on commit 272907f

Please sign in to comment.