1 /*
2 * Copyright (c) 2023, 2025, 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 jdk.internal.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 Util.toInternalName(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 }