Skip to content

Commit ede74e3

Browse files
committed
Delay creation of advice remapper+cache until needed
1 parent d402356 commit ede74e3

File tree

5 files changed

+80
-64
lines changed

5 files changed

+80
-64
lines changed

dd-java-agent/agent-builder/src/main/java/datadog/trace/agent/tooling/ShadedAdviceLocator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public ShadedAdviceLocator(ClassLoader adviceLoader, AdviceShader adviceShader)
1717
public Resolution locate(String className) throws IOException {
1818
final Resolution resolution = adviceLocator.locate(className);
1919
if (resolution.isResolved()) {
20-
return new Resolution.Explicit(adviceShader.shade(resolution.resolve()));
20+
return new Resolution.Explicit(adviceShader.shadeClass(resolution.resolve()));
2121
} else {
2222
return resolution;
2323
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/AdviceShader.java

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10,89 +10,105 @@
1010
import net.bytebuddy.jar.asm.commons.Remapper;
1111

1212
/** Shades advice bytecode by applying relocations to all references. */
13-
public final class AdviceShader extends Remapper {
14-
private final DDCache<String, String> cache = DDCaches.newFixedSizeCache(64);
13+
public final class AdviceShader {
14+
private final Map<String, String> relocations;
1515

16-
/** Flattened sequence of old-prefix, new-prefix relocations. */
17-
private final String[] prefixes;
16+
private volatile Remapper remapper;
1817

1918
public static AdviceShader with(Map<String, String> relocations) {
20-
return relocations != null ? new AdviceShader(relocations) : null;
19+
if (relocations != null) {
20+
return new AdviceShader(relocations);
21+
}
22+
return null;
2123
}
2224

23-
AdviceShader(Map<String, String> relocations) {
24-
// convert relocations to a flattened sequence: old-prefix, new-prefix, etc.
25-
this.prefixes = new String[relocations.size() * 2];
26-
int i = 0;
27-
for (Map.Entry<String, String> e : relocations.entrySet()) {
28-
String oldPrefix = e.getKey();
29-
String newPrefix = e.getValue();
30-
if (oldPrefix.indexOf('.') > 0) {
31-
// accept dotted prefixes, but store them in their internal form
32-
this.prefixes[i++] = oldPrefix.replace('.', '/');
33-
this.prefixes[i++] = newPrefix.replace('.', '/');
34-
} else {
35-
this.prefixes[i++] = oldPrefix;
36-
this.prefixes[i++] = newPrefix;
37-
}
38-
}
25+
private AdviceShader(Map<String, String> relocations) {
26+
this.relocations = relocations;
3927
}
4028

4129
/** Applies shading before calling the given {@link ClassVisitor}. */
42-
public ClassVisitor shade(ClassVisitor cv) {
43-
return new ClassRemapper(cv, this);
30+
public ClassVisitor shadeClass(ClassVisitor cv) {
31+
if (null == remapper) {
32+
remapper = new AdviceMapper();
33+
}
34+
return new ClassRemapper(cv, remapper);
4435
}
4536

4637
/** Returns the result of shading the given bytecode. */
47-
public byte[] shade(byte[] bytecode) {
38+
public byte[] shadeClass(byte[] bytecode) {
4839
ClassReader cr = new ClassReader(bytecode);
4940
ClassWriter cw = new ClassWriter(null, 0);
50-
cr.accept(shade(cw), 0);
41+
cr.accept(shadeClass(cw), 0);
5142
return cw.toByteArray();
5243
}
5344

54-
@Override
55-
public String map(String internalName) {
56-
if (internalName.startsWith("java/")
57-
|| internalName.startsWith("datadog/")
58-
|| internalName.startsWith("net/bytebuddy/")) {
59-
return internalName; // never shade these references
45+
final class AdviceMapper extends Remapper {
46+
private final DDCache<String, String> mappingCache = DDCaches.newFixedSizeCache(64);
47+
48+
/** Flattened sequence of old-prefix, new-prefix relocations. */
49+
private final String[] prefixes;
50+
51+
AdviceMapper() {
52+
// convert relocations to a flattened sequence: old-prefix, new-prefix, etc.
53+
this.prefixes = new String[relocations.size() * 2];
54+
int i = 0;
55+
for (Map.Entry<String, String> e : relocations.entrySet()) {
56+
String oldPrefix = e.getKey();
57+
String newPrefix = e.getValue();
58+
if (oldPrefix.indexOf('.') > 0) {
59+
// accept dotted prefixes, but store them in their internal form
60+
this.prefixes[i++] = oldPrefix.replace('.', '/');
61+
this.prefixes[i++] = newPrefix.replace('.', '/');
62+
} else {
63+
this.prefixes[i++] = oldPrefix;
64+
this.prefixes[i++] = newPrefix;
65+
}
66+
}
6067
}
61-
return cache.computeIfAbsent(internalName, this::shade);
62-
}
6368

64-
@Override
65-
public Object mapValue(Object value) {
66-
if (value instanceof String) {
67-
String text = (String) value;
68-
if (text.isEmpty()) {
69-
return text;
70-
} else if (text.indexOf('.') > 0) {
71-
return shadeDottedName(text);
69+
@Override
70+
public String map(String internalName) {
71+
if (internalName.startsWith("java/")
72+
|| internalName.startsWith("datadog/")
73+
|| internalName.startsWith("net/bytebuddy/")) {
74+
return internalName; // never shade these references
75+
}
76+
return mappingCache.computeIfAbsent(internalName, this::shadeInternalName);
77+
}
78+
79+
@Override
80+
public Object mapValue(Object value) {
81+
if (value instanceof String) {
82+
String text = (String) value;
83+
if (text.isEmpty()) {
84+
return text;
85+
} else if (text.indexOf('.') > 0) {
86+
return shadeDottedName(text);
87+
} else {
88+
return shadeInternalName(text);
89+
}
7290
} else {
73-
return shade(text);
91+
return super.mapValue(value);
7492
}
75-
} else {
76-
return super.mapValue(value);
7793
}
78-
}
7994

80-
private String shade(String internalName) {
81-
for (int i = 0; i < prefixes.length; i += 2) {
82-
if (internalName.startsWith(prefixes[i])) {
83-
return prefixes[i + 1] + internalName.substring(prefixes[i].length());
95+
private String shadeInternalName(String internalName) {
96+
for (int i = 0; i < prefixes.length; i += 2) {
97+
if (internalName.startsWith(prefixes[i])) {
98+
return prefixes[i + 1] + internalName.substring(prefixes[i].length());
99+
}
84100
}
101+
return internalName;
85102
}
86-
return internalName;
87-
}
88103

89-
private String shadeDottedName(String name) {
90-
String internalName = name.replace('.', '/');
91-
for (int i = 0; i < prefixes.length; i += 2) {
92-
if (internalName.startsWith(prefixes[i])) {
93-
return prefixes[i + 1].replace('/', '.') + name.substring(prefixes[i].length());
104+
private String shadeDottedName(String name) {
105+
String internalName = name.replace('.', '/');
106+
for (int i = 0; i < prefixes.length; i += 2) {
107+
if (internalName.startsWith(prefixes[i])) {
108+
return prefixes[i + 1].replace('/', '.') + name.substring(prefixes[i].length());
109+
}
94110
}
111+
return name;
95112
}
96-
return name;
97113
}
98114
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/HelperInjector.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,12 @@ public HelperInjector(
8989
private Map<String, byte[]> getHelperMap() throws IOException {
9090
if (dynamicTypeMap.isEmpty()) {
9191
final Map<String, byte[]> classnameToBytes = new LinkedHashMap<>();
92-
for (final String helperClassName : helperClassNames) {
93-
byte[] classBytes = classFileLocator.locate(helperClassName).resolve();
92+
for (String helperName : helperClassNames) {
93+
byte[] classBytes = classFileLocator.locate(helperName).resolve();
9494
if (adviceShader != null) {
95-
classBytes = adviceShader.shade(classBytes);
95+
classBytes = adviceShader.shadeClass(classBytes);
9696
}
97-
classnameToBytes.put(helperClassName, classBytes);
97+
classnameToBytes.put(helperName, classBytes);
9898
}
9999

100100
return classnameToBytes;

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private static Map<String, byte[]> createHelperMap(final InstrumenterModule modu
132132
ClassFileLocator.ForClassLoader.of(module.getClass().getClassLoader());
133133
byte[] classBytes = locator.locate(helperName).resolve();
134134
if (null != adviceShader) {
135-
classBytes = adviceShader.shade(classBytes);
135+
classBytes = adviceShader.shadeClass(classBytes);
136136
}
137137
helperMap.put(helperName, classBytes);
138138
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceCreator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public static Map<String, Reference> createReferencesFrom(
7070
if (null == adviceShader) {
7171
reader.accept(cv, ClassReader.SKIP_FRAMES);
7272
} else {
73-
reader.accept(adviceShader.shade(cv), ClassReader.SKIP_FRAMES);
73+
reader.accept(adviceShader.shadeClass(cv), ClassReader.SKIP_FRAMES);
7474
}
7575

7676
final Map<String, Reference> instrumentationReferences = cv.getReferences();

0 commit comments

Comments
 (0)