1 /* 2 * Copyright (c) 2023, 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.PreloadAttribute; 60 import java.lang.classfile.attribute.PermittedSubclassesAttribute; 61 import java.lang.classfile.attribute.RecordAttribute; 62 import java.lang.classfile.attribute.RecordComponentInfo; 63 import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute; 64 import java.lang.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute; 65 import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute; 66 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; 67 import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute; 68 import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute; 69 import java.lang.classfile.attribute.SignatureAttribute; 70 import java.lang.classfile.components.ClassRemapper; 71 import java.lang.classfile.constantpool.Utf8Entry; 72 import java.lang.classfile.instruction.ConstantInstruction.LoadConstantInstruction; 73 import java.lang.classfile.instruction.ExceptionCatch; 74 import java.lang.classfile.instruction.FieldInstruction; 75 import java.lang.classfile.instruction.InvokeDynamicInstruction; 76 import java.lang.classfile.instruction.InvokeInstruction; 77 import java.lang.classfile.instruction.LocalVariable; 78 import java.lang.classfile.instruction.LocalVariableType; 79 import java.lang.classfile.instruction.NewMultiArrayInstruction; 80 import java.lang.classfile.instruction.NewObjectInstruction; 81 import java.lang.classfile.instruction.NewReferenceArrayInstruction; 82 import java.lang.classfile.instruction.TypeCheckInstruction; 83 84 import java.lang.constant.ClassDesc; 85 import java.lang.constant.ConstantDesc; 86 import java.lang.constant.DirectMethodHandleDesc; 87 import java.lang.constant.DynamicCallSiteDesc; 88 import java.lang.constant.DynamicConstantDesc; 89 import java.lang.constant.MethodHandleDesc; 90 import java.lang.constant.MethodTypeDesc; 91 import java.util.List; 92 import java.util.function.Function; 93 94 public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) implements ClassRemapper { 95 96 @Override 97 public void accept(ClassBuilder clb, ClassElement cle) { 98 switch (cle) { 99 case FieldModel fm -> 100 clb.withField(fm.fieldName().stringValue(), map( 101 fm.fieldTypeSymbol()), fb -> 102 fm.forEachElement(asFieldTransform().resolve(fb).consumer())); 103 case MethodModel mm -> 104 clb.withMethod(mm.methodName().stringValue(), mapMethodDesc( 105 mm.methodTypeSymbol()), mm.flags().flagsMask(), mb -> 106 mm.forEachElement(asMethodTransform().resolve(mb).consumer())); 107 case Superclass sc -> 108 clb.withSuperclass(map(sc.superclassEntry().asSymbol())); 109 case Interfaces ins -> 110 clb.withInterfaceSymbols(Util.mappedList(ins.interfaces(), in -> 111 map(in.asSymbol()))); 112 case SignatureAttribute sa -> 113 clb.with(SignatureAttribute.of(mapClassSignature(sa.asClassSignature()))); 114 case InnerClassesAttribute ica -> 115 clb.with(InnerClassesAttribute.of(ica.classes().stream().map(ici -> 116 InnerClassInfo.of(map(ici.innerClass().asSymbol()), 117 ici.outerClass().map(oc -> map(oc.asSymbol())), 118 ici.innerName().map(Utf8Entry::stringValue), 119 ici.flagsMask())).toList())); 120 case EnclosingMethodAttribute ema -> 121 clb.with(EnclosingMethodAttribute.of(map(ema.enclosingClass().asSymbol()), 122 ema.enclosingMethodName().map(Utf8Entry::stringValue), 123 ema.enclosingMethodTypeSymbol().map(this::mapMethodDesc))); 124 case RecordAttribute ra -> 125 clb.with(RecordAttribute.of(ra.components().stream() 126 .map(this::mapRecordComponent).toList())); 127 case ModuleAttribute ma -> 128 clb.with(ModuleAttribute.of(ma.moduleName(), ma.moduleFlagsMask(), 129 ma.moduleVersion().orElse(null), 130 ma.requires(), ma.exports(), ma.opens(), 131 ma.uses().stream().map(ce -> 132 clb.constantPool().classEntry(map(ce.asSymbol()))).toList(), 133 ma.provides().stream().map(mp -> 134 ModuleProvideInfo.of(map(mp.provides().asSymbol()), 135 mp.providesWith().stream().map(pw -> 136 map(pw.asSymbol())).toList())).toList())); 137 case NestHostAttribute nha -> 138 clb.with(NestHostAttribute.of(map(nha.nestHost().asSymbol()))); 139 case NestMembersAttribute nma -> 140 clb.with(NestMembersAttribute.ofSymbols(nma.nestMembers().stream() 141 .map(nm -> map(nm.asSymbol())).toList())); 142 case PermittedSubclassesAttribute psa -> 143 clb.with(PermittedSubclassesAttribute.ofSymbols( 144 psa.permittedSubclasses().stream().map(ps -> 145 map(ps.asSymbol())).toList())); 146 case PreloadAttribute pa -> 147 clb.with(PreloadAttribute.ofSymbols( 148 pa.preloads().stream().map(pc -> 149 map(pc.asSymbol())).toList())); 150 case RuntimeVisibleAnnotationsAttribute aa -> 151 clb.with(RuntimeVisibleAnnotationsAttribute.of( 152 mapAnnotations(aa.annotations()))); 153 case RuntimeInvisibleAnnotationsAttribute aa -> 154 clb.with(RuntimeInvisibleAnnotationsAttribute.of( 155 mapAnnotations(aa.annotations()))); 156 case RuntimeVisibleTypeAnnotationsAttribute aa -> 157 clb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 158 mapTypeAnnotations(aa.annotations()))); 159 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 160 clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 161 mapTypeAnnotations(aa.annotations()))); 162 default -> 163 clb.with(cle); 164 } 165 } 166 167 @Override 168 public FieldTransform asFieldTransform() { 169 return (FieldBuilder fb, FieldElement fe) -> { 170 switch (fe) { 171 case SignatureAttribute sa -> 172 fb.with(SignatureAttribute.of( 173 mapSignature(sa.asTypeSignature()))); 174 case RuntimeVisibleAnnotationsAttribute aa -> 175 fb.with(RuntimeVisibleAnnotationsAttribute.of( 176 mapAnnotations(aa.annotations()))); 177 case RuntimeInvisibleAnnotationsAttribute aa -> 178 fb.with(RuntimeInvisibleAnnotationsAttribute.of( 179 mapAnnotations(aa.annotations()))); 180 case RuntimeVisibleTypeAnnotationsAttribute aa -> 181 fb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 182 mapTypeAnnotations(aa.annotations()))); 183 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 184 fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 185 mapTypeAnnotations(aa.annotations()))); 186 default -> 187 fb.with(fe); 188 } 189 }; 190 } 191 192 @Override 193 public MethodTransform asMethodTransform() { 194 return (MethodBuilder mb, MethodElement me) -> { 195 switch (me) { 196 case AnnotationDefaultAttribute ada -> 197 mb.with(AnnotationDefaultAttribute.of( 198 mapAnnotationValue(ada.defaultValue()))); 199 case CodeModel com -> 200 mb.transformCode(com, asCodeTransform()); 201 case ExceptionsAttribute ea -> 202 mb.with(ExceptionsAttribute.ofSymbols( 203 ea.exceptions().stream().map(ce -> 204 map(ce.asSymbol())).toList())); 205 case SignatureAttribute sa -> 206 mb.with(SignatureAttribute.of( 207 mapMethodSignature(sa.asMethodSignature()))); 208 case RuntimeVisibleAnnotationsAttribute aa -> 209 mb.with(RuntimeVisibleAnnotationsAttribute.of( 210 mapAnnotations(aa.annotations()))); 211 case RuntimeInvisibleAnnotationsAttribute aa -> 212 mb.with(RuntimeInvisibleAnnotationsAttribute.of( 213 mapAnnotations(aa.annotations()))); 214 case RuntimeVisibleParameterAnnotationsAttribute paa -> 215 mb.with(RuntimeVisibleParameterAnnotationsAttribute.of( 216 paa.parameterAnnotations().stream() 217 .map(this::mapAnnotations).toList())); 218 case RuntimeInvisibleParameterAnnotationsAttribute paa -> 219 mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of( 220 paa.parameterAnnotations().stream() 221 .map(this::mapAnnotations).toList())); 222 case RuntimeVisibleTypeAnnotationsAttribute aa -> 223 mb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 224 mapTypeAnnotations(aa.annotations()))); 225 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 226 mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 227 mapTypeAnnotations(aa.annotations()))); 228 default -> 229 mb.with(me); 230 } 231 }; 232 } 233 234 @Override 235 public CodeTransform asCodeTransform() { 236 return (CodeBuilder cob, CodeElement coe) -> { 237 switch (coe) { 238 case FieldInstruction fai -> 239 cob.fieldInstruction(fai.opcode(), map(fai.owner().asSymbol()), 240 fai.name().stringValue(), map(fai.typeSymbol())); 241 case InvokeInstruction ii -> 242 cob.invokeInstruction(ii.opcode(), map(ii.owner().asSymbol()), 243 ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()), 244 ii.isInterface()); 245 case InvokeDynamicInstruction idi -> 246 cob.invokeDynamicInstruction(DynamicCallSiteDesc.of( 247 idi.bootstrapMethod(), idi.name().stringValue(), 248 mapMethodDesc(idi.typeSymbol()), 249 idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new))); 250 case NewObjectInstruction c -> 251 cob.newObjectInstruction(map(c.className().asSymbol())); 252 case NewReferenceArrayInstruction c -> 253 cob.anewarray(map(c.componentType().asSymbol())); 254 case NewMultiArrayInstruction c -> 255 cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions()); 256 case TypeCheckInstruction c -> 257 cob.typeCheckInstruction(c.opcode(), map(c.type().asSymbol())); 258 case ExceptionCatch c -> 259 cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType() 260 .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol())))); 261 case LocalVariable c -> 262 cob.localVariable(c.slot(), c.name().stringValue(), map(c.typeSymbol()), 263 c.startScope(), c.endScope()); 264 case LocalVariableType c -> 265 cob.localVariableType(c.slot(), c.name().stringValue(), 266 mapSignature(c.signatureSymbol()), c.startScope(), c.endScope()); 267 case LoadConstantInstruction ldc -> 268 cob.constantInstruction(ldc.opcode(), 269 mapConstantValue(ldc.constantValue())); 270 case RuntimeVisibleTypeAnnotationsAttribute aa -> 271 cob.with(RuntimeVisibleTypeAnnotationsAttribute.of( 272 mapTypeAnnotations(aa.annotations()))); 273 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 274 cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 275 mapTypeAnnotations(aa.annotations()))); 276 default -> 277 cob.with(coe); 278 } 279 }; 280 } 281 282 @Override 283 public ClassDesc map(ClassDesc desc) { 284 if (desc == null) return null; 285 if (desc.isArray()) return map(desc.componentType()).arrayType(); 286 if (desc.isPrimitive()) return desc; 287 return mapFunction.apply(desc); 288 } 289 290 MethodTypeDesc mapMethodDesc(MethodTypeDesc desc) { 291 return MethodTypeDesc.of(map(desc.returnType()), 292 desc.parameterList().stream().map(this::map).toArray(ClassDesc[]::new)); 293 } 294 295 ClassSignature mapClassSignature(ClassSignature signature) { 296 return ClassSignature.of(mapTypeParams(signature.typeParameters()), 297 mapSignature(signature.superclassSignature()), 298 signature.superinterfaceSignatures().stream() 299 .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new)); 300 } 301 302 MethodSignature mapMethodSignature(MethodSignature signature) { 303 return MethodSignature.of(mapTypeParams(signature.typeParameters()), 304 signature.throwableSignatures().stream().map(this::mapSignature).toList(), 305 mapSignature(signature.result()), 306 signature.arguments().stream() 307 .map(this::mapSignature).toArray(Signature[]::new)); 308 } 309 310 RecordComponentInfo mapRecordComponent(RecordComponentInfo component) { 311 return RecordComponentInfo.of(component.name().stringValue(), 312 map(component.descriptorSymbol()), 313 component.attributes().stream().map(atr -> 314 switch (atr) { 315 case SignatureAttribute sa -> 316 SignatureAttribute.of( 317 mapSignature(sa.asTypeSignature())); 318 case RuntimeVisibleAnnotationsAttribute aa -> 319 RuntimeVisibleAnnotationsAttribute.of( 320 mapAnnotations(aa.annotations())); 321 case RuntimeInvisibleAnnotationsAttribute aa -> 322 RuntimeInvisibleAnnotationsAttribute.of( 323 mapAnnotations(aa.annotations())); 324 case RuntimeVisibleTypeAnnotationsAttribute aa -> 325 RuntimeVisibleTypeAnnotationsAttribute.of( 326 mapTypeAnnotations(aa.annotations())); 327 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 328 RuntimeInvisibleTypeAnnotationsAttribute.of( 329 mapTypeAnnotations(aa.annotations())); 330 default -> atr; 331 }).toList()); 332 } 333 334 DirectMethodHandleDesc mapDirectMethodHandle(DirectMethodHandleDesc dmhd) { 335 return switch (dmhd.kind()) { 336 case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> 337 MethodHandleDesc.ofField(dmhd.kind(), map(dmhd.owner()), 338 dmhd.methodName(), 339 map(ClassDesc.ofDescriptor(dmhd.lookupDescriptor()))); 340 default -> 341 MethodHandleDesc.ofMethod(dmhd.kind(), map(dmhd.owner()), 342 dmhd.methodName(), 343 mapMethodDesc(MethodTypeDesc.ofDescriptor(dmhd.lookupDescriptor()))); 344 }; 345 } 346 347 ConstantDesc mapConstantValue(ConstantDesc value) { 348 return switch (value) { 349 case ClassDesc cd -> 350 map(cd); 351 case DynamicConstantDesc<?> dcd -> 352 mapDynamicConstant(dcd); 353 case DirectMethodHandleDesc dmhd -> 354 mapDirectMethodHandle(dmhd); 355 case MethodTypeDesc mtd -> 356 mapMethodDesc(mtd); 357 default -> value; 358 }; 359 } 360 361 DynamicConstantDesc<?> mapDynamicConstant(DynamicConstantDesc<?> dcd) { 362 return DynamicConstantDesc.ofNamed(mapDirectMethodHandle(dcd.bootstrapMethod()), 363 dcd.constantName(), 364 map(dcd.constantType()), 365 dcd.bootstrapArgsList().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)); 366 } 367 368 @SuppressWarnings("unchecked") 369 <S extends Signature> S mapSignature(S signature) { 370 return (S) switch (signature) { 371 case Signature.ArrayTypeSig ats -> 372 Signature.ArrayTypeSig.of(mapSignature(ats.componentSignature())); 373 case Signature.ClassTypeSig cts -> 374 Signature.ClassTypeSig.of( 375 cts.outerType().map(this::mapSignature).orElse(null), 376 map(cts.classDesc()), 377 cts.typeArgs().stream() 378 .map(ta -> Signature.TypeArg.of( 379 ta.wildcardIndicator(), 380 ta.boundType().map(this::mapSignature))) 381 .toArray(Signature.TypeArg[]::new)); 382 default -> signature; 383 }; 384 } 385 386 List<Annotation> mapAnnotations(List<Annotation> annotations) { 387 return annotations.stream().map(this::mapAnnotation).toList(); 388 } 389 390 Annotation mapAnnotation(Annotation a) { 391 return Annotation.of(map(a.classSymbol()), a.elements().stream().map(el -> 392 AnnotationElement.of(el.name(), mapAnnotationValue(el.value()))).toList()); 393 } 394 395 AnnotationValue mapAnnotationValue(AnnotationValue val) { 396 return switch (val) { 397 case AnnotationValue.OfAnnotation oa -> 398 AnnotationValue.ofAnnotation(mapAnnotation(oa.annotation())); 399 case AnnotationValue.OfArray oa -> 400 AnnotationValue.ofArray(oa.values().stream().map(this::mapAnnotationValue).toList()); 401 case AnnotationValue.OfConstant oc -> oc; 402 case AnnotationValue.OfClass oc -> 403 AnnotationValue.ofClass(map(oc.classSymbol())); 404 case AnnotationValue.OfEnum oe -> 405 AnnotationValue.ofEnum(map(oe.classSymbol()), oe.constantName().stringValue()); 406 }; 407 } 408 409 List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) { 410 return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(), 411 a.targetPath(), map(a.classSymbol()), 412 a.elements().stream().map(el -> AnnotationElement.of(el.name(), 413 mapAnnotationValue(el.value()))).toList())).toList(); 414 } 415 416 List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) { 417 return typeParams.stream().map(tp -> Signature.TypeParam.of(tp.identifier(), 418 tp.classBound().map(this::mapSignature), 419 tp.interfaceBounds().stream() 420 .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new))).toList(); 421 } 422 423 }