10
10
import java .lang .reflect .Method ;
11
11
import java .lang .reflect .Modifier ;
12
12
import java .util .Arrays ;
13
- import java .util .HashMap ;
14
13
import java .util .HashSet ;
14
+ import java .util .concurrent .ConcurrentHashMap ;
15
15
16
16
/**
17
17
* This class contains most of Xposed's central logic, such as initialization and callbacks used by
18
18
* the native side. It also includes methods to add new hooks.
19
+ * <p>
20
+ * Latest Update 2018/01/20
19
21
*/
20
22
@ SuppressWarnings ("WeakerAccess" )
21
23
public final class XposedBridge {
@@ -33,7 +35,7 @@ public final class XposedBridge {
33
35
private static final Object [] EMPTY_ARRAY = new Object [0 ];
34
36
35
37
// built-in handlers
36
- private static final HashMap <Member , AdditionalHookInfo > sHookedMethodInfos = new HashMap <>();
38
+ private static final ConcurrentHashMap <Member , AdditionalHookInfo > sHookedMethodInfos = new ConcurrentHashMap <>();
37
39
38
40
/**
39
41
* Writes a message to the logcat error log.
@@ -70,30 +72,28 @@ public static void log(final Throwable t) {
70
72
public static XC_MethodHook .Unhook hookMethod (final Member hookMethod , final XC_MethodHook callback ) {
71
73
if (!(hookMethod instanceof Method ) && !(hookMethod instanceof Constructor <?>)) {
72
74
throw new IllegalArgumentException ("Only methods and constructors can be hooked: " + hookMethod .toString ());
73
- } else if (hookMethod .getDeclaringClass ().isInterface ()) {
74
- throw new IllegalArgumentException ("Cannot hook interfaces: " + hookMethod .toString ());
75
75
} else if (Modifier .isAbstract (hookMethod .getModifiers ())) {
76
76
throw new IllegalArgumentException ("Cannot hook abstract methods: " + hookMethod .toString ());
77
77
}
78
78
79
- AdditionalHookInfo additionalInfo ;
80
- synchronized (sHookedMethodInfos ) {
81
- additionalInfo = sHookedMethodInfos .get (hookMethod );
82
- }
83
-
79
+ AdditionalHookInfo additionalInfo = sHookedMethodInfos .get (hookMethod );
84
80
if (additionalInfo == null ) {
85
81
if (Modifier .isStatic (hookMethod .getModifiers ()))
86
82
AndHook .ensureClassInitialized (hookMethod .getDeclaringClass ());
87
83
additionalInfo = new AdditionalHookInfo (hookMethod , AndHook .backup (hookMethod ));
88
84
if (additionalInfo .slot == -1 )
89
85
throw new RuntimeException ("Failed to backup methods: " + hookMethod .toString ());
90
86
91
- sHookedMethodInfos .put (hookMethod , additionalInfo );
92
87
additionalInfo .callbacks .add (callback );
93
88
if (!AndHook .hook (hookMethod , additionalInfo , additionalInfo .slot ))
94
89
throw new RuntimeException ("Failed to hook methods: " + hookMethod .toString ());
95
90
91
+ sHookedMethodInfos .put (hookMethod , additionalInfo );
96
92
} else {
93
+ // sanity check
94
+ if (!additionalInfo .method .getDeclaringClass ().getClassLoader ().equals (hookMethod .getDeclaringClass ().getClassLoader ())) {
95
+ throw new RuntimeException ("Unexpected same methods within difference CL: " + hookMethod .toString ());
96
+ }
97
97
additionalInfo .callbacks .add (callback );
98
98
}
99
99
@@ -111,10 +111,7 @@ public static XC_MethodHook.Unhook hookMethod(final Member hookMethod, final XC_
111
111
@ SuppressWarnings ("all" )
112
112
@ Deprecated
113
113
public static void unhookMethod (final Member hookMethod , final XC_MethodHook callback ) {
114
- AdditionalHookInfo additionalInfo ;
115
- synchronized (sHookedMethodInfos ) {
116
- additionalInfo = sHookedMethodInfos .get (hookMethod );
117
- }
114
+ final AdditionalHookInfo additionalInfo = sHookedMethodInfos .get (hookMethod );
118
115
if (additionalInfo != null ) {
119
116
additionalInfo .callbacks .remove (callback );
120
117
}
@@ -126,9 +123,7 @@ public static void unhookMethod(final Member hookMethod, final XC_MethodHook cal
126
123
* AndHook extension function.
127
124
*/
128
125
public static boolean unhookMethod (final int slot , final Member hookMethod ) {
129
- synchronized (sHookedMethodInfos ) {
130
- sHookedMethodInfos .remove (hookMethod );
131
- }
126
+ sHookedMethodInfos .remove (hookMethod );
132
127
return AndHook .restore (slot , hookMethod );
133
128
}
134
129
@@ -192,6 +187,7 @@ public static HashSet<XC_MethodHook.Unhook> hookAllConstructors(final Class<?> h
192
187
/**
193
188
* This method is called as a replacement for hooked methods.
194
189
*/
190
+ @ SuppressWarnings ("unused" )
195
191
private static Object handleHookedMethod (final Object additionalInfoObj ,
196
192
final Object thisObject , final Object [] args ) throws Throwable {
197
193
final AdditionalHookInfo additionalInfo = (AdditionalHookInfo ) additionalInfoObj ;
@@ -275,7 +271,7 @@ private static Object handleHookedMethod(final Object additionalInfoObj,
275
271
* if the original method should be skipped.
276
272
*/
277
273
public static Object invokeOriginalMethod (final int slot , final Object thisObject ,
278
- final Object [] args ) throws Throwable {
274
+ final Object [] args ) {
279
275
return AndHook .invokeMethod (slot , thisObject , args );
280
276
}
281
277
@@ -339,14 +335,5 @@ private AdditionalHookInfo(final Member method, final int slot) {
339
335
this .method = method ;
340
336
this .slot = slot ;
341
337
}
342
-
343
- /**
344
- * AndHook method bridge.
345
- */
346
- @ SuppressWarnings ("unused" )
347
- private static Object bridge (final Object thiz , final Object receiver , final Object [] args )
348
- throws Throwable {
349
- return XposedBridge .handleHookedMethod (thiz , receiver , args );
350
- }
351
338
}
352
339
}
0 commit comments