Skip to content

Commit 2e84689

Browse files
authored
Merge pull request #210 from jselbo/fix-jvmtiagent-extractnativelibs
Fix JvmtiAgent native library load when extractNativeLibs=false
2 parents f1f5ff7 + 9f5757f commit 2e84689

1 file changed

Lines changed: 50 additions & 1 deletion

File tree

  • dexmaker-mockito-inline/src/main/java/com/android/dx/mockito/inline

dexmaker-mockito-inline/src/main/java/com/android/dx/mockito/inline/JvmtiAgent.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.os.Debug;
2121

2222
import java.io.File;
23+
import java.io.FileInputStream;
2324
import java.io.FileOutputStream;
2425
import java.io.IOException;
2526
import java.io.InputStream;
@@ -62,10 +63,58 @@ class JvmtiAgent {
6263
+ "by a BaseDexClassLoader");
6364
}
6465

65-
Debug.attachJvmtiAgent(AGENT_LIB_NAME, null, cl);
66+
String agentPath = resolveAgentPath(cl);
67+
Debug.attachJvmtiAgent(agentPath, null, cl);
6668
nativeRegisterTransformerHook();
6769
}
6870

71+
/**
72+
* Resolve the agent library to a path that Debug.attachJvmtiAgent can load.
73+
*
74+
* <p>Debug.attachJvmtiAgent rejects paths containing '=' (used as options
75+
* separator). On Android, app install directories may contain '=' in their
76+
* path (e.g. /data/app/~~K6yx...A==/pkg-axiN...Q==/). When findLibrary
77+
* returns such a path, or returns null (extractNativeLibs=false), we copy
78+
* the library to a temp file.
79+
*/
80+
private static String resolveAgentPath(ClassLoader cl) throws IOException {
81+
String path = ((BaseDexClassLoader) cl).findLibrary("dexmakerjvmtiagent");
82+
83+
if (path != null && !path.contains("=")) {
84+
return path;
85+
}
86+
87+
// Copy the library to a temp file with a clean path.
88+
File copiedAgent = File.createTempFile("org.mockito.android.agent", ".so");
89+
copiedAgent.deleteOnExit();
90+
91+
InputStream is;
92+
if (path != null) {
93+
is = new FileInputStream(path);
94+
} else {
95+
// findLibrary returned null — try loading from APK resources
96+
String abi = Build.SUPPORTED_ABIS[0];
97+
String resourcePath = "lib/" + abi + "/" + AGENT_LIB_NAME;
98+
is = cl.getResourceAsStream(resourcePath);
99+
if (is == null) {
100+
throw new IOException("Could not find " + AGENT_LIB_NAME
101+
+ " via findLibrary or classloader resources");
102+
}
103+
}
104+
105+
try (OutputStream os = new FileOutputStream(copiedAgent)) {
106+
byte[] buffer = new byte[64 * 1024];
107+
int numRead;
108+
while ((numRead = is.read(buffer)) != -1) {
109+
os.write(buffer, 0, numRead);
110+
}
111+
} finally {
112+
is.close();
113+
}
114+
115+
return copiedAgent.getAbsolutePath();
116+
}
117+
69118
private native void nativeUnregisterTransformerHook();
70119

71120
@Override

0 commit comments

Comments
 (0)