1 /* 2 * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.internal.classfile.impl; 26 27 import java.lang.classfile.Annotation; 28 import java.lang.classfile.AnnotationElement; 29 import java.lang.classfile.AnnotationValue; 30 import java.lang.classfile.ClassBuilder; 31 import java.lang.classfile.ClassElement; 32 import java.lang.classfile.ClassSignature; 33 import java.lang.classfile.CodeBuilder; 34 import java.lang.classfile.CodeElement; 35 import java.lang.classfile.CodeModel; 36 import java.lang.classfile.CodeTransform; 37 import java.lang.classfile.FieldBuilder; 38 import java.lang.classfile.FieldElement; 39 import java.lang.classfile.FieldModel; 40 import java.lang.classfile.FieldTransform; 41 import java.lang.classfile.Interfaces; 42 import java.lang.classfile.MethodBuilder; 43 import java.lang.classfile.MethodElement; 44 import java.lang.classfile.MethodModel; 45 import java.lang.classfile.MethodSignature; 46 import java.lang.classfile.MethodTransform; 47 import java.lang.classfile.Signature; 48 import java.lang.classfile.Superclass; 49 import java.lang.classfile.TypeAnnotation; 50 import java.lang.classfile.attribute.AnnotationDefaultAttribute; 51 import java.lang.classfile.attribute.EnclosingMethodAttribute; 52 import java.lang.classfile.attribute.ExceptionsAttribute; 53 import java.lang.classfile.attribute.InnerClassInfo; 54 import java.lang.classfile.attribute.InnerClassesAttribute; 55 import java.lang.classfile.attribute.ModuleAttribute; 56 import java.lang.classfile.attribute.ModuleProvideInfo; 57 import java.lang.classfile.attribute.NestHostAttribute; 58 import java.lang.classfile.attribute.NestMembersAttribute; 59 import java.lang.classfile.attribute.PermittedSubclassesAttribute; 60 import java.lang.classfile.attribute.RecordAttribute; 61 import java.lang.classfile.attribute.RecordComponentInfo; 62 import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; 63 import java.lang.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute; 64 import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute; 65 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; 66 import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute; 67 import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; 68 import java.lang.classfile.attribute.SignatureAttribute; 69 import java.lang.classfile.components.ClassRemapper; 70 import java.lang.classfile.constantpool.Utf8Entry; 71 import java.lang.classfile.instruction.ConstantInstruction.LoadConstantInstruction; 72 import java.lang.classfile.instruction.ExceptionCatch; 73 import java.lang.classfile.instruction.FieldInstruction; 74 import java.lang.classfile.instruction.InvokeDynamicInstruction; 75 import java.lang.classfile.instruction.InvokeInstruction; 76 import java.lang.classfile.instruction.LocalVariable; 77 import java.lang.classfile.instruction.LocalVariableType; 78 import java.lang.classfile.instruction.NewMultiArrayInstruction; 79 import java.lang.classfile.instruction.NewObjectInstruction; 80 import java.lang.classfile.instruction.NewReferenceArrayInstruction; 81 import java.lang.classfile.instruction.TypeCheckInstruction; 82 83 import java.lang.constant.ClassDesc; 84 import java.lang.constant.ConstantDesc; 85 import java.lang.constant.DirectMethodHandleDesc; 86 import java.lang.constant.DynamicCallSiteDesc; 87 import java.lang.constant.DynamicConstantDesc; 88 import java.lang.constant.MethodHandleDesc; 89 import java.lang.constant.MethodTypeDesc; 90 import java.util.List; 91 import java.util.function.Function; 92 93 public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) implements ClassRemapper { 94 95 @Override 96 public void accept(ClassBuilder clb, ClassElement cle) { 97 switch (cle) { 98 case FieldModel fm -> 99 clb.withField(fm.fieldName().stringValue(), map( 100 fm.fieldTypeSymbol()), fb -> fb.transform(fm, asFieldTransform())); 101 case MethodModel mm -> 102 clb.withMethod(mm.methodName().stringValue(), mapMethodDesc( 103 mm.methodTypeSymbol()), mm.flags().flagsMask(), mb -> mb.transform(mm, asMethodTransform())); 104 case Superclass sc -> 105 clb.withSuperclass(map(sc.superclassEntry().asSymbol())); 106 case Interfaces ins -> 107 clb.withInterfaceSymbols(Util.mappedList(ins.interfaces(), in -> 108 map(in.asSymbol()))); 109 case SignatureAttribute sa -> 110 clb.with(SignatureAttribute.of(mapClassSignature(sa.asClassSignature()))); 111 case InnerClassesAttribute ica -> 112 clb.with(InnerClassesAttribute.of(ica.classes().stream().map(ici -> 113 InnerClassInfo.of(map(ici.innerClass().asSymbol()), 114 ici.outerClass().map(oc -> map(oc.asSymbol())), 115 ici.innerName().map(Utf8Entry::stringValue), 116 ici.flagsMask())).toList())); 117 case EnclosingMethodAttribute ema -> 118 clb.with(EnclosingMethodAttribute.of(map(ema.enclosingClass().asSymbol()), 119 ema.enclosingMethodName().map(Utf8Entry::stringValue), 120 ema.enclosingMethodTypeSymbol().map(this::mapMethodDesc))); 121 case RecordAttribute ra -> 122 clb.with(RecordAttribute.of(ra.components().stream() 123 .map(this::mapRecordComponent).toList())); 124 case ModuleAttribute ma -> 125 clb.with(ModuleAttribute.of(ma.moduleName(), ma.moduleFlagsMask(), 126 ma.moduleVersion().orElse(null), 127 ma.requires(), ma.exports(), ma.opens(), 128 ma.uses().stream().map(ce -> 129 clb.constantPool().classEntry(map(ce.asSymbol()))).toList(), 130 ma.provides().stream().map(mp -> 131 ModuleProvideInfo.of(map(mp.provides().asSymbol()), 132 mp.providesWith().stream().map(pw -> 133 map(pw.asSymbol())).toList())).toList())); 134 case NestHostAttribute nha -> 135 clb.with(NestHostAttribute.of(map(nha.nestHost().asSymbol()))); 136 case NestMembersAttribute nma -> 137 clb.with(NestMembersAttribute.ofSymbols(nma.nestMembers().stream() 138 .map(nm -> map(nm.asSymbol())).toList())); 139 case PermittedSubclassesAttribute psa -> 140 clb.with(PermittedSubclassesAttribute.ofSymbols( 141 psa.permittedSubclasses().stream().map(ps -> 142 map(ps.asSymbol())).toList())); 143 case RuntimeVisibleAnnotationsAttribute aa -> 144 clb.with(RuntimeVisibleAnnotationsAttribute.of( 145 mapAnnotations(aa.annotations()))); 146 case RuntimeInvisibleAnnotationsAttribute aa -> 147 clb.with(RuntimeInvisibleAnnotationsAttribute.of( 148 mapAnnotations(aa.annotations()))); 149 case RuntimeVisibleTypeAnnotationsAttribute aa -> 150 clb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 151 mapTypeAnnotations(aa.annotations()))); 152 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 153 clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 154 mapTypeAnnotations(aa.annotations()))); 155 default -> 156 clb.with(cle); 157 } 158 } 159 160 @Override 161 public FieldTransform asFieldTransform() { 162 return (FieldBuilder fb, FieldElement fe) -> { 163 switch (fe) { 164 case SignatureAttribute sa -> 165 fb.with(SignatureAttribute.of( 166 mapSignature(sa.asTypeSignature()))); 167 case RuntimeVisibleAnnotationsAttribute aa -> 168 fb.with(RuntimeVisibleAnnotationsAttribute.of( 169 mapAnnotations(aa.annotations()))); 170 case RuntimeInvisibleAnnotationsAttribute aa -> 171 fb.with(RuntimeInvisibleAnnotationsAttribute.of( 172 mapAnnotations(aa.annotations()))); 173 case RuntimeVisibleTypeAnnotationsAttribute aa -> 174 fb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 175 mapTypeAnnotations(aa.annotations()))); 176 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 177 fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 178 mapTypeAnnotations(aa.annotations()))); 179 default -> 180 fb.with(fe); 181 } 182 }; 183 } 184 185 @Override 186 public MethodTransform asMethodTransform() { 187 return (MethodBuilder mb, MethodElement me) -> { 188 switch (me) { 189 case AnnotationDefaultAttribute ada -> 190 mb.with(AnnotationDefaultAttribute.of( 191 mapAnnotationValue(ada.defaultValue()))); 192 case CodeModel com -> 193 mb.transformCode(com, asCodeTransform()); 194 case ExceptionsAttribute ea -> 195 mb.with(ExceptionsAttribute.ofSymbols( 196 ea.exceptions().stream().map(ce -> 197 map(ce.asSymbol())).toList())); 198 case SignatureAttribute sa -> 199 mb.with(SignatureAttribute.of( 200 mapMethodSignature(sa.asMethodSignature()))); 201 case RuntimeVisibleAnnotationsAttribute aa -> 202 mb.with(RuntimeVisibleAnnotationsAttribute.of( 203 mapAnnotations(aa.annotations()))); 204 case RuntimeInvisibleAnnotationsAttribute aa -> 205 mb.with(RuntimeInvisibleAnnotationsAttribute.of( 206 mapAnnotations(aa.annotations()))); 207 case RuntimeVisibleParameterAnnotationsAttribute paa -> 208 mb.with(RuntimeVisibleParameterAnnotationsAttribute.of( 209 paa.parameterAnnotations().stream() 210 .map(this::mapAnnotations).toList())); 211 case RuntimeInvisibleParameterAnnotationsAttribute paa -> 212 mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of( 213 paa.parameterAnnotations().stream() 214 .map(this::mapAnnotations).toList())); 215 case RuntimeVisibleTypeAnnotationsAttribute aa -> 216 mb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 217 mapTypeAnnotations(aa.annotations()))); 218 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 219 mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 220 mapTypeAnnotations(aa.annotations()))); 221 default -> 222 mb.with(me); 223 } 224 }; 225 } 226 227 @Override 228 public CodeTransform asCodeTransform() { 229 return (CodeBuilder cob, CodeElement coe) -> { 230 switch (coe) { 231 case FieldInstruction fai -> 232 cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()), 233 fai.name().stringValue(), map(fai.typeSymbol())); 234 case InvokeInstruction ii -> 235 cob.invoke(ii.opcode(), map(ii.owner().asSymbol()), 236 ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()), 237 ii.isInterface()); 238 case InvokeDynamicInstruction idi -> 239 cob.invokedynamic(DynamicCallSiteDesc.of( 240 mapDirectMethodHandle(idi.bootstrapMethod()), idi.name().stringValue(), 241 mapMethodDesc(idi.typeSymbol()), 242 idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new))); 243 case NewObjectInstruction c -> 244 cob.new_(map(c.className().asSymbol())); 245 case NewReferenceArrayInstruction c -> 246 cob.anewarray(map(c.componentType().asSymbol())); 247 case NewMultiArrayInstruction c -> 248 cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions()); 249 case TypeCheckInstruction c -> 250 cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol()))); 251 case ExceptionCatch c -> 252 cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType() 253 .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol())))); 254 case LocalVariable c -> 255 cob.localVariable(c.slot(), c.name().stringValue(), map(c.typeSymbol()), 256 c.startScope(), c.endScope()); 257 case LocalVariableType c -> 258 cob.localVariableType(c.slot(), c.name().stringValue(), 259 mapSignature(c.signatureSymbol()), c.startScope(), c.endScope()); 260 case LoadConstantInstruction ldc -> 261 cob.ldc(mapConstantValue(ldc.constantValue())); 262 case RuntimeVisibleTypeAnnotationsAttribute aa -> 263 cob.with(RuntimeVisibleTypeAnnotationsAttribute.of( 264 mapTypeAnnotations(aa.annotations()))); 265 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 266 cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 267 mapTypeAnnotations(aa.annotations()))); 268 default -> 269 cob.with(coe); 270 } 271 }; 272 } 273 274 @Override 275 public ClassDesc map(ClassDesc desc) { 276 if (desc == null) return null; 277 if (desc.isArray()) return map(desc.componentType()).arrayType(); 278 if (desc.isPrimitive()) return desc; 279 return mapFunction.apply(desc); 280 } 281 282 MethodTypeDesc mapMethodDesc(MethodTypeDesc desc) { 283 return MethodTypeDesc.of(map(desc.returnType()), 284 desc.parameterList().stream().map(this::map).toArray(ClassDesc[]::new)); 285 } 286 287 ClassSignature mapClassSignature(ClassSignature signature) { 288 return ClassSignature.of(mapTypeParams(signature.typeParameters()), 289 mapSignature(signature.superclassSignature()), 290 signature.superinterfaceSignatures().stream() 291 .map(this::mapSignature).toArray(Signature.ClassTypeSig[]::new)); 292 } 293 294 MethodSignature mapMethodSignature(MethodSignature signature) { 295 return MethodSignature.of(mapTypeParams(signature.typeParameters()), 296 signature.throwableSignatures().stream().map(this::mapSignature).toList(), 297 mapSignature(signature.result()), 298 signature.arguments().stream() 299 .map(this::mapSignature).toArray(Signature[]::new)); 300 } 301 302 RecordComponentInfo mapRecordComponent(RecordComponentInfo component) { 303 return RecordComponentInfo.of(component.name().stringValue(), 304 map(component.descriptorSymbol()), 305 component.attributes().stream().map(atr -> 306 switch (atr) { 307 case SignatureAttribute sa -> 308 SignatureAttribute.of( 309 mapSignature(sa.asTypeSignature())); 310 case RuntimeVisibleAnnotationsAttribute aa -> 311 RuntimeVisibleAnnotationsAttribute.of( 312 mapAnnotations(aa.annotations())); 313 case RuntimeInvisibleAnnotationsAttribute aa -> 314 RuntimeInvisibleAnnotationsAttribute.of( 315 mapAnnotations(aa.annotations())); 316 case RuntimeVisibleTypeAnnotationsAttribute aa -> 317 RuntimeVisibleTypeAnnotationsAttribute.of( 318 mapTypeAnnotations(aa.annotations())); 319 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 320 RuntimeInvisibleTypeAnnotationsAttribute.of( 321 mapTypeAnnotations(aa.annotations())); 322 default -> atr; 323 }).toList()); 324 } 325 326 DirectMethodHandleDesc mapDirectMethodHandle(DirectMethodHandleDesc dmhd) { 327 return switch (dmhd.kind()) { 328 case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> 329 MethodHandleDesc.ofField(dmhd.kind(), map(dmhd.owner()), 330 dmhd.methodName(), 331 map(ClassDesc.ofDescriptor(dmhd.lookupDescriptor()))); 332 default -> 333 MethodHandleDesc.ofMethod(dmhd.kind(), map(dmhd.owner()), 334 dmhd.methodName(), 335 mapMethodDesc(MethodTypeDesc.ofDescriptor(dmhd.lookupDescriptor()))); 336 }; 337 } 338 339 ConstantDesc mapConstantValue(ConstantDesc value) { 340 return switch (value) { 341 case ClassDesc cd -> 342 map(cd); 343 case DynamicConstantDesc<?> dcd -> 344 mapDynamicConstant(dcd); 345 case DirectMethodHandleDesc dmhd -> 346 mapDirectMethodHandle(dmhd); 347 case MethodTypeDesc mtd -> 348 mapMethodDesc(mtd); 349 default -> value; 350 }; 351 } 352 353 DynamicConstantDesc<?> mapDynamicConstant(DynamicConstantDesc<?> dcd) { 354 return DynamicConstantDesc.ofNamed(mapDirectMethodHandle(dcd.bootstrapMethod()), 355 dcd.constantName(), 356 map(dcd.constantType()), 357 dcd.bootstrapArgsList().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)); 358 } 359 360 @SuppressWarnings("unchecked") 361 <S extends Signature> S mapSignature(S signature) { 362 return (S) switch (signature) { 363 case Signature.ArrayTypeSig ats -> 364 Signature.ArrayTypeSig.of(mapSignature(ats.componentSignature())); 365 case Signature.ClassTypeSig cts -> 366 Signature.ClassTypeSig.of( 367 cts.outerType().map(this::mapSignature).orElse(null), 368 map(cts.classDesc()), 369 cts.typeArgs().stream().map(ta -> switch (ta) { 370 case Signature.TypeArg.Unbounded u -> u; 371 case Signature.TypeArg.Bounded bta -> Signature.TypeArg.bounded( 372 bta.wildcardIndicator(), mapSignature(bta.boundType())); 373 }).toArray(Signature.TypeArg[]::new)); 374 default -> signature; 375 }; 376 } 377 378 List<Annotation> mapAnnotations(List<Annotation> annotations) { 379 return annotations.stream().map(this::mapAnnotation).toList(); 380 } 381 382 Annotation mapAnnotation(Annotation a) { 383 return Annotation.of(map(a.classSymbol()), a.elements().stream().map(el -> 384 AnnotationElement.of(el.name(), mapAnnotationValue(el.value()))).toList()); 385 } 386 387 AnnotationValue mapAnnotationValue(AnnotationValue val) { 388 return switch (val) { 389 case AnnotationValue.OfAnnotation oa -> 390 AnnotationValue.ofAnnotation(mapAnnotation(oa.annotation())); 391 case AnnotationValue.OfArray oa -> 392 AnnotationValue.ofArray(oa.values().stream().map(this::mapAnnotationValue).toList()); 393 case AnnotationValue.OfConstant oc -> oc; 394 case AnnotationValue.OfClass oc -> 395 AnnotationValue.ofClass(map(oc.classSymbol())); 396 case AnnotationValue.OfEnum oe -> 397 AnnotationValue.ofEnum(map(oe.classSymbol()), oe.constantName().stringValue()); 398 }; 399 } 400 401 List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) { 402 return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(), 403 a.targetPath(), mapAnnotation(a.annotation()))).toList(); 404 } 405 406 List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) { 407 return typeParams.stream().map(tp -> Signature.TypeParam.of(tp.identifier(), 408 tp.classBound().map(this::mapSignature), 409 tp.interfaceBounds().stream() 410 .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new))).toList(); 411 } 412 413 }