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