rovo89 / XposedBridge

The Java part of the Xposed framework.
3.91k stars 1.1k forks source link

ClassNotFoundException #72

Closed wangduheng closed 9 years ago

wangduheng commented 9 years ago

help on nexus5 Android 6.0 Marshmallow 11-17 15:44:59.147 E/Xposed (32485): de.robv.android.xposed.XposedHelpers$ClassNotFoundError: java.lang.ClassNotFoundException: com.android.server.pm.PackageManagerService

    final Class<?> clsPMS = XposedHelpers.findClass("com.android.server.pm.PackageManagerService", this.getClass().getClassLoader());
liudongmiao commented 9 years ago

Since Android 5.X, the service now use a seperate class loader. And possible codes can be found in many project, for example, XPrivacy, Prevent Running. A possible entry can be like this:

XposedBridge.hookAllMethods(ActivityThread.class, "systemMain", ...)

When systemMain is caled, you can get the classloader. As ActivityThread is in framework.jar, but is called in services.jar (and only services.jar).

rovo89 commented 9 years ago

@liudongmiao Yes, the correct classloader has to be used. But why would you want to hook systemMain() yourself? Xposed already does this and other stuff for you. You just need to implement handleLoadPackage() and look for package "android". Then use lpparam.classLoader like for normal apps. See http://forum.xda-developers.com/showpost.php?p=58840569&postcount=7

liudongmiao commented 9 years ago

@rovo89 In my case, I need to hook ActivityManagerService at the very beginning. But handleLoadPackage is hooked in handleBindApplication, so I just hook at the very beginning.

rovo89 commented 9 years ago

Not sure if I understand you correctly. Xposed is doing this: https://github.com/rovo89/XposedBridge/blob/art/src/de/robv/android/xposed/XposedBridge.java#L199 So it calls handleLoadPackage from the systemMain callback for this specific case.

liudongmiao commented 9 years ago

@rovo89 yes, it's ok for latest version, and I didn't refer to the branch art. And as I need to hook ActivityManagerService too, I don't want to write the androdi-related/xposed-related module, so the module can be use for most android / xposed version.

And from my side, Xposed Bridge should only offer basic function, and move the real things (hack system service and so) to Xposed Installer using DexClassLoader or so.

rovo89 commented 9 years ago

I totally agree with you that XposedBridge as Java part of the framework should only hook whatever is necessary to provide a good environment for modules. And I think it does. Hooking the installer to inject the current version might be the only questionable hook, but I think it makes sense. Show me any other hook and I'll tell you why it's required as part of the framework.

I have no idea where you see the framework hacking a system service. If you're referring to the package manager hook, that's because otherwise there would be bootloops on some ROMs (with no modules installed), so it's absolutely required for Xposed to run. For details, see 01c324454bb0e7eba82ae56895b04fb571ba5073

I also didn't understand what you mean with "I don't want to write the androdi-related/xposed-related module - aren't all modules related to Android and Xposed? None of them would work with iOS or without Xposed...

Anyway, what I told you about handleLoadPackage with dummy package name android is actually the best way to keep your module working all Android versions. You will be able to find the ActivityManagerService class using the classloader provided by this callback. The only thing you need to take care for are possibly changed method signatures. Yes, before Lollipop, you could hook system services in initZygote, but in fact, the better way would have been the one I described because that's the process where they're actually executed. This kind of abstraction requires very few hooks placed by the framework, but it makes it much easier for module developers because they don't need to reinvent the wheel and worry about different versions each time.

rovo89 commented 9 years ago

Forgot to mention: I don't agree that the Xposed Installer should hook anything. Either it's part of the framework because it's required to run Xposed or to provide entry points for module developers, or it's not part of the framework. The installer doesn't need any hooks for itself.

You could of course think of things like hacking the Settings app to include a menu item that opens Xposed Installer. In that case, the hook should indeed be done by the installer. But I'm not a fan of that anyway.