@@ -16,6 +16,12 @@ object ReflectionUtils {
1616  import  scala .reflect .runtime .{ universe  =>  ru  }
1717  import  ru ._ 
1818
19+   val  JavaVersion :  Int  = 
20+     System .getProperty(" java.version"  ).split(" \\ ."  ) match  {
21+       case  Array (" 1"  , v, _* ) =>  v.toInt //  Java 8 style: 1.8.x
22+       case  Array (v, _* )      =>  v.toInt //  Java 9+ style: 11.x, 17.x, etc.
23+     }
24+ 
1925  implicit  def  symbolToMethodSymbol (sym : Symbol ):  Symbols # MethodSymbol  =  sym.asInstanceOf [Symbols # MethodSymbol ]
2026
2127  private  val  mirror  =  runtimeMirror(getClass.getClassLoader)
@@ -51,29 +57,23 @@ object ReflectionUtils {
5157    def  returnsValueClass :  Boolean  =  findTypeSymbol.exists(_.returnType.typeSymbol.isDerivedValueClass)
5258
5359    private  def  resolveWithScalaGenerics :  Option [Class [_]] = 
54-       scala.util
55-         .Try  {
56-           findTypeSymbol
57-             .filter(_.returnType.typeSymbol.isClass)
58-             .map(_.asMethod.returnType.typeSymbol.asClass)
59-             .map(mirror.runtimeClass)
60-         }
61-         .toOption
62-         .flatten
60+       uTry {
61+         findTypeSymbol
62+           .filter(_.returnType.typeSymbol.isClass)
63+           .map(_.asMethod.returnType.typeSymbol.asClass)
64+           .map(mirror.runtimeClass)
65+       }.toOption.flatten
6366
6467    private  def  findTypeSymbol  = 
65-       scala.util
66-         .Try  {
67-           mirror
68-             .classSymbol(method.getDeclaringClass)
69-             .info
70-             .decls
71-             .collectFirst {
72-               case  symbol if  isNonConstructorMethod(symbol) &&  customMirror.methodToJava(symbol) ===  method =>  symbol
73-             }
74-         }
75-         .toOption
76-         .flatten
68+       uTry {
69+         mirror
70+           .classSymbol(method.getDeclaringClass)
71+           .info
72+           .decls
73+           .collectFirst {
74+             case  symbol if  isNonConstructorMethod(symbol) &&  customMirror.methodToJava(symbol) ===  method =>  symbol
75+           }
76+       }.toOption.flatten
7777
7878    private  def  resolveWithJavaGenerics :  Option [Class [_]] = 
7979      try  Some (GenericsResolver .resolve(invocation.getMock.getClass).`type`(method.getDeclaringClass).method(method).resolveReturnClass())
@@ -85,45 +85,47 @@ object ReflectionUtils {
8585  private  def  isNonConstructorMethod (d : ru.Symbol ):  Boolean  =  d.isMethod &&  ! d.isConstructor
8686
8787  def  extraInterfaces [T ](implicit  $wtt : WeakTypeTag [T ], $ct : ClassTag [T ]):  List [Class [_]] = 
88-     scala.util
89-       .Try  {
90-         val  cls  =  clazz($ct)
91-         $wtt.tpe match  {
92-           case  RefinedType (types, _) => 
93-             types.map($wtt.mirror.runtimeClass).collect {
94-               case  c : Class [_] if  c.isInterface &&  c !=  cls =>  c
95-             }
96-           case  _ =>  List .empty
97-         }
88+     uTry {
89+       val  cls  =  clazz($ct)
90+       $wtt.tpe match  {
91+         case  RefinedType (types, _) => 
92+           types.map($wtt.mirror.runtimeClass).collect {
93+             case  c : Class [_] if  c.isInterface &&  c !=  cls =>  c
94+           }
95+         case  _ =>  List .empty
9896      }
99-        .toOption
97+     } .toOption
10098      .getOrElse(List .empty)
10199
102100  def  methodsWithLazyOrVarArgs (classes : Seq [Class [_]]):  Seq [(Method , Set [Int ])] = 
103101    classes.flatMap { clazz => 
104-       scala.util
105-         .Try  {
106-           mirror
107-             .classSymbol(clazz)
108-             .info
109-             .members
110-             .collect {
111-               case  symbol if  isNonConstructorMethod(symbol) => 
112-                 symbol ->  symbol.typeSignature.paramLists.flatten.zipWithIndex.collect {
113-                   case  (p, idx) if  p.typeSignature.toString.startsWith(" =>"  ) =>  idx
114-                   case  (p, idx) if  p.typeSignature.toString.endsWith(" *"  )    =>  idx
115-                 }.toSet
116-             }
117-             .collect {
118-               case  (symbol, indices) if  indices.nonEmpty =>  customMirror.methodToJava(symbol) ->  indices
119-             }
120-             .toSeq
121-         }
122-         .toOption
102+       uTry {
103+         mirror
104+           .classSymbol(clazz)
105+           .info
106+           .members
107+           .collect {
108+             case  symbol if  isNonConstructorMethod(symbol) => 
109+               symbol ->  symbol.typeSignature.paramLists.flatten.zipWithIndex.collect {
110+                 case  (p, idx) if  p.typeSignature.toString.startsWith(" =>"  ) =>  idx
111+                 case  (p, idx) if  p.typeSignature.toString.endsWith(" *"  )    =>  idx
112+               }.toSet
113+           }
114+           .collect {
115+             case  (symbol, indices) if  indices.nonEmpty =>  customMirror.methodToJava(symbol) ->  indices
116+           }
117+           .toSeq
118+       }.toOption
123119        .getOrElse(Seq .empty)
124120    }
125121
126-   def  setFinalStatic (field : Field , newValue : Any ):  Unit  =  {
122+   def  setFinalStatic (field : Field , newValue : AnyRef ):  Unit  = 
123+     if  (JavaVersion  <  17 )
124+       setFinalStatic17Minus(field, newValue)
125+     else 
126+       setFinalStatic17Plus(field, newValue)
127+ 
128+   private  def  setFinalStatic17Minus (field : Field , newValue : AnyRef ):  Unit  =  {
127129    val  clazz  =  classOf [java.lang.Class [_]]
128130    field.setAccessible(true )
129131    val  modifiersField :  Field  =  uTry(clazz.getDeclaredField(" modifiers"  )) match  {
@@ -150,4 +152,34 @@ object ReflectionUtils {
150152    field.set(null , newValue)
151153  }
152154
155+   private  def  setFinalStatic17Plus (field : Field , newValue : AnyRef ):  Unit  = 
156+     try  {
157+       //  Try to get Unsafe instance (works with both sun.misc.Unsafe and jdk.internal.misc.Unsafe)
158+       val  unsafeClass :  Class [_] = 
159+         try 
160+           Class .forName(" sun.misc.Unsafe"  )
161+         catch  {
162+           case  _ : ClassNotFoundException  =>  Class .forName(" jdk.internal.misc.Unsafe"  )
163+         }
164+ 
165+       val  unsafeField  =  unsafeClass.getDeclaredField(" theUnsafe"  )
166+       unsafeField.setAccessible(true )
167+       val  unsafe  =  unsafeField.get(null )
168+ 
169+       //  Get methods via reflection to handle both Unsafe implementations
170+       val  staticFieldBaseMethod    =  unsafeClass.getMethod(" staticFieldBase"  , classOf [Field ])
171+       val  staticFieldOffsetMethod  =  unsafeClass.getMethod(" staticFieldOffset"  , classOf [Field ])
172+       val  putObjectMethod          =  unsafeClass.getMethod(" putObject"  , classOf [Object ], classOf [Long ], classOf [Object ])
173+ 
174+       //  Get base and offset for the field
175+       val  base :  Object  =  staticFieldBaseMethod.invoke(unsafe, field)
176+       val  offset :  Long  =  staticFieldOffsetMethod.invoke(unsafe, field).asInstanceOf [Long ]
177+ 
178+       //  Set the field value directly
179+       putObjectMethod.invoke(unsafe, base, java.lang.Long .valueOf(offset), newValue)
180+     } catch  {
181+       case  NonFatal (e) => 
182+         throw  new  IllegalStateException (s " Cannot modify final field  ${field.getName}" , e)
183+     }
184+ 
153185}
0 commit comments