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 RuntimeVisibleAnnotationsAttribute aa -> 88 clb.with(RuntimeVisibleAnnotationsAttribute.of( 89 mapAnnotations(aa.annotations()))); 90 case RuntimeInvisibleAnnotationsAttribute aa -> 91 clb.with(RuntimeInvisibleAnnotationsAttribute.of( 92 mapAnnotations(aa.annotations()))); 93 case RuntimeVisibleTypeAnnotationsAttribute aa -> 94 clb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 95 mapTypeAnnotations(aa.annotations()))); 96 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 97 clb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 98 mapTypeAnnotations(aa.annotations()))); 99 default -> 100 clb.with(cle); 101 } 102 } 103 104 @Override 105 public FieldTransform asFieldTransform() { 106 return (FieldBuilder fb, FieldElement fe) -> { 107 switch (fe) { 108 case SignatureAttribute sa -> 109 fb.with(SignatureAttribute.of( 110 mapSignature(sa.asTypeSignature()))); 111 case RuntimeVisibleAnnotationsAttribute aa -> 112 fb.with(RuntimeVisibleAnnotationsAttribute.of( 113 mapAnnotations(aa.annotations()))); 114 case RuntimeInvisibleAnnotationsAttribute aa -> 115 fb.with(RuntimeInvisibleAnnotationsAttribute.of( 116 mapAnnotations(aa.annotations()))); 117 case RuntimeVisibleTypeAnnotationsAttribute aa -> 118 fb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 119 mapTypeAnnotations(aa.annotations()))); 120 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 121 fb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 122 mapTypeAnnotations(aa.annotations()))); 123 default -> 124 fb.with(fe); 125 } 126 }; 127 } 128 129 @Override 130 public MethodTransform asMethodTransform() { 131 return (MethodBuilder mb, MethodElement me) -> { 132 switch (me) { 133 case AnnotationDefaultAttribute ada -> 134 mb.with(AnnotationDefaultAttribute.of( 135 mapAnnotationValue(ada.defaultValue()))); 136 case CodeModel com -> 137 mb.transformCode(com, asCodeTransform()); 138 case ExceptionsAttribute ea -> 139 mb.with(ExceptionsAttribute.ofSymbols( 140 ea.exceptions().stream().map(ce -> 141 map(ce.asSymbol())).toList())); 142 case SignatureAttribute sa -> 143 mb.with(SignatureAttribute.of( 144 mapMethodSignature(sa.asMethodSignature()))); 145 case RuntimeVisibleAnnotationsAttribute aa -> 146 mb.with(RuntimeVisibleAnnotationsAttribute.of( 147 mapAnnotations(aa.annotations()))); 148 case RuntimeInvisibleAnnotationsAttribute aa -> 149 mb.with(RuntimeInvisibleAnnotationsAttribute.of( 150 mapAnnotations(aa.annotations()))); 151 case RuntimeVisibleParameterAnnotationsAttribute paa -> 152 mb.with(RuntimeVisibleParameterAnnotationsAttribute.of( 153 paa.parameterAnnotations().stream() 154 .map(this::mapAnnotations).toList())); 155 case RuntimeInvisibleParameterAnnotationsAttribute paa -> 156 mb.with(RuntimeInvisibleParameterAnnotationsAttribute.of( 157 paa.parameterAnnotations().stream() 158 .map(this::mapAnnotations).toList())); 159 case RuntimeVisibleTypeAnnotationsAttribute aa -> 160 mb.with(RuntimeVisibleTypeAnnotationsAttribute.of( 161 mapTypeAnnotations(aa.annotations()))); 162 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 163 mb.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 164 mapTypeAnnotations(aa.annotations()))); 165 default -> 166 mb.with(me); 167 } 168 }; 169 } 170 171 @Override 172 public CodeTransform asCodeTransform() { 173 return (CodeBuilder cob, CodeElement coe) -> { 174 switch (coe) { 175 case FieldInstruction fai -> 176 cob.fieldAccess(fai.opcode(), map(fai.owner().asSymbol()), 177 fai.name().stringValue(), map(fai.typeSymbol())); 178 case InvokeInstruction ii -> 179 cob.invoke(ii.opcode(), map(ii.owner().asSymbol()), 180 ii.name().stringValue(), mapMethodDesc(ii.typeSymbol()), 181 ii.isInterface()); 182 case InvokeDynamicInstruction idi -> 183 cob.invokedynamic(DynamicCallSiteDesc.of( 184 mapDirectMethodHandle(idi.bootstrapMethod()), idi.name().stringValue(), 185 mapMethodDesc(idi.typeSymbol()), 186 idi.bootstrapArgs().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new))); 187 case NewObjectInstruction c -> 188 cob.new_(map(c.className().asSymbol())); 189 case NewReferenceArrayInstruction c -> 190 cob.anewarray(map(c.componentType().asSymbol())); 191 case NewMultiArrayInstruction c -> 192 cob.multianewarray(map(c.arrayType().asSymbol()), c.dimensions()); 193 case TypeCheckInstruction c -> 194 cob.with(TypeCheckInstruction.of(c.opcode(), map(c.type().asSymbol()))); 195 case ExceptionCatch c -> 196 cob.exceptionCatch(c.tryStart(), c.tryEnd(), c.handler(),c.catchType() 197 .map(d -> TemporaryConstantPool.INSTANCE.classEntry(map(d.asSymbol())))); 198 case LocalVariable c -> 199 cob.localVariable(c.slot(), c.name().stringValue(), map(c.typeSymbol()), 200 c.startScope(), c.endScope()); 201 case LocalVariableType c -> 202 cob.localVariableType(c.slot(), c.name().stringValue(), 203 mapSignature(c.signatureSymbol()), c.startScope(), c.endScope()); 204 case LoadConstantInstruction ldc -> 205 cob.ldc(mapConstantValue(ldc.constantValue())); 206 case RuntimeVisibleTypeAnnotationsAttribute aa -> 207 cob.with(RuntimeVisibleTypeAnnotationsAttribute.of( 208 mapTypeAnnotations(aa.annotations()))); 209 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 210 cob.with(RuntimeInvisibleTypeAnnotationsAttribute.of( 211 mapTypeAnnotations(aa.annotations()))); 212 default -> 213 cob.with(coe); 214 } 215 }; 216 } 217 218 @Override 219 public ClassDesc map(ClassDesc desc) { 220 if (desc == null) return null; 221 if (desc.isArray()) return map(desc.componentType()).arrayType(); 222 if (desc.isPrimitive()) return desc; 223 return mapFunction.apply(desc); 224 } 225 226 MethodTypeDesc mapMethodDesc(MethodTypeDesc desc) { 227 return MethodTypeDesc.of(map(desc.returnType()), 228 desc.parameterList().stream().map(this::map).toArray(ClassDesc[]::new)); 229 } 230 231 ClassSignature mapClassSignature(ClassSignature signature) { 232 return ClassSignature.of(mapTypeParams(signature.typeParameters()), 233 mapSignature(signature.superclassSignature()), 234 signature.superinterfaceSignatures().stream() 235 .map(this::mapSignature).toArray(Signature.ClassTypeSig[]::new)); 236 } 237 238 MethodSignature mapMethodSignature(MethodSignature signature) { 239 return MethodSignature.of(mapTypeParams(signature.typeParameters()), 240 signature.throwableSignatures().stream().map(this::mapSignature).toList(), 241 mapSignature(signature.result()), 242 signature.arguments().stream() 243 .map(this::mapSignature).toArray(Signature[]::new)); 244 } 245 246 RecordComponentInfo mapRecordComponent(RecordComponentInfo component) { 247 return RecordComponentInfo.of(component.name().stringValue(), 248 map(component.descriptorSymbol()), 249 component.attributes().stream().map(atr -> 250 switch (atr) { 251 case SignatureAttribute sa -> 252 SignatureAttribute.of( 253 mapSignature(sa.asTypeSignature())); 254 case RuntimeVisibleAnnotationsAttribute aa -> 255 RuntimeVisibleAnnotationsAttribute.of( 256 mapAnnotations(aa.annotations())); 257 case RuntimeInvisibleAnnotationsAttribute aa -> 258 RuntimeInvisibleAnnotationsAttribute.of( 259 mapAnnotations(aa.annotations())); 260 case RuntimeVisibleTypeAnnotationsAttribute aa -> 261 RuntimeVisibleTypeAnnotationsAttribute.of( 262 mapTypeAnnotations(aa.annotations())); 263 case RuntimeInvisibleTypeAnnotationsAttribute aa -> 264 RuntimeInvisibleTypeAnnotationsAttribute.of( 265 mapTypeAnnotations(aa.annotations())); 266 default -> atr; 267 }).toList()); 268 } 269 270 DirectMethodHandleDesc mapDirectMethodHandle(DirectMethodHandleDesc dmhd) { 271 return switch (dmhd.kind()) { 272 case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> 273 MethodHandleDesc.ofField(dmhd.kind(), map(dmhd.owner()), 274 dmhd.methodName(), 275 map(ClassDesc.ofDescriptor(dmhd.lookupDescriptor()))); 276 default -> 277 MethodHandleDesc.ofMethod(dmhd.kind(), map(dmhd.owner()), 278 dmhd.methodName(), 279 mapMethodDesc(MethodTypeDesc.ofDescriptor(dmhd.lookupDescriptor()))); 280 }; 281 } 282 283 ConstantDesc mapConstantValue(ConstantDesc value) { 284 return switch (value) { 285 case ClassDesc cd -> 286 map(cd); 287 case DynamicConstantDesc<?> dcd -> 288 mapDynamicConstant(dcd); 289 case DirectMethodHandleDesc dmhd -> 290 mapDirectMethodHandle(dmhd); 291 case MethodTypeDesc mtd -> 292 mapMethodDesc(mtd); 293 default -> value; 294 }; 295 } 296 297 DynamicConstantDesc<?> mapDynamicConstant(DynamicConstantDesc<?> dcd) { 298 return DynamicConstantDesc.ofNamed(mapDirectMethodHandle(dcd.bootstrapMethod()), 299 dcd.constantName(), 300 map(dcd.constantType()), 301 dcd.bootstrapArgsList().stream().map(this::mapConstantValue).toArray(ConstantDesc[]::new)); 302 } 303 304 @SuppressWarnings("unchecked") 305 <S extends Signature> S mapSignature(S signature) { 306 return (S) switch (signature) { 307 case Signature.ArrayTypeSig ats -> 308 Signature.ArrayTypeSig.of(mapSignature(ats.componentSignature())); 309 case Signature.ClassTypeSig cts -> 310 Signature.ClassTypeSig.of( 311 cts.outerType().map(this::mapSignature).orElse(null), 312 map(cts.classDesc()), 313 cts.typeArgs().stream().map(ta -> switch (ta) { 314 case Signature.TypeArg.Unbounded u -> u; 315 case Signature.TypeArg.Bounded bta -> Signature.TypeArg.bounded( 316 bta.wildcardIndicator(), mapSignature(bta.boundType())); 317 }).toArray(Signature.TypeArg[]::new)); 318 default -> signature; 319 }; 320 } 321 322 List<Annotation> mapAnnotations(List<Annotation> annotations) { 323 return annotations.stream().map(this::mapAnnotation).toList(); 324 } 325 326 Annotation mapAnnotation(Annotation a) { 327 return Annotation.of(map(a.classSymbol()), a.elements().stream().map(el -> 328 AnnotationElement.of(el.name(), mapAnnotationValue(el.value()))).toList()); 329 } 330 331 AnnotationValue mapAnnotationValue(AnnotationValue val) { 332 return switch (val) { 333 case AnnotationValue.OfAnnotation oa -> 334 AnnotationValue.ofAnnotation(mapAnnotation(oa.annotation())); 335 case AnnotationValue.OfArray oa -> 336 AnnotationValue.ofArray(oa.values().stream().map(this::mapAnnotationValue).toList()); 337 case AnnotationValue.OfConstant oc -> oc; 338 case AnnotationValue.OfClass oc -> 339 AnnotationValue.ofClass(map(oc.classSymbol())); 340 case AnnotationValue.OfEnum oe -> 341 AnnotationValue.ofEnum(map(oe.classSymbol()), oe.constantName().stringValue()); 342 }; 343 } 344 345 List<TypeAnnotation> mapTypeAnnotations(List<TypeAnnotation> typeAnnotations) { 346 return typeAnnotations.stream().map(a -> TypeAnnotation.of(a.targetInfo(), 347 a.targetPath(), mapAnnotation(a.annotation()))).toList(); 348 } 349 350 List<Signature.TypeParam> mapTypeParams(List<Signature.TypeParam> typeParams) { 351 return typeParams.stream().map(tp -> Signature.TypeParam.of(tp.identifier(), 352 tp.classBound().map(this::mapSignature), 353 tp.interfaceBounds().stream() 354 .map(this::mapSignature).toArray(Signature.RefTypeSig[]::new))).toList(); 355 } 356 357 }