{"id":13482543,"url":"https://github.com/canyie/pine","last_synced_at":"2025-05-14T12:12:50.048Z","repository":{"id":40678629,"uuid":"258964898","full_name":"canyie/pine","owner":"canyie","description":"Dynamic java method hook framework on ART. Allowing you to change almost all java methods' behavior dynamically.","archived":false,"fork":false,"pushed_at":"2025-02-10T03:53:43.000Z","size":21890,"stargazers_count":1221,"open_issues_count":25,"forks_count":219,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-04-11T21:48:33.024Z","etag":null,"topics":["android","aop","aop-framework","art","art-runtime","hook","hook-framework","hooking","java-hook","xposed"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/canyie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-04-26T07:13:21.000Z","updated_at":"2025-04-11T18:46:09.000Z","dependencies_parsed_at":"2022-07-14T07:10:28.263Z","dependency_job_id":"561083bb-75f2-4ee8-be52-b8c3f3267b70","html_url":"https://github.com/canyie/pine","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canyie%2Fpine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canyie%2Fpine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canyie%2Fpine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/canyie%2Fpine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/canyie","download_url":"https://codeload.github.com/canyie/pine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254140768,"owners_count":22021220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","aop","aop-framework","art","art-runtime","hook","hook-framework","hooking","java-hook","xposed"],"created_at":"2024-07-31T17:01:03.120Z","updated_at":"2025-05-14T12:12:45.030Z","avatar_url":"https://github.com/canyie.png","language":"Java","readme":"# Pine [![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n\n[中文版本](README_cn.md)\n## Introduction\nPine is a dynamic java method hook framework on ART runtime, which can intercept almost all java method calls in the current process.\n\nCurrently it supports Android 4.4(ART only) ~ **15 Beta 4** with thumb-2/arm64 architecture.\n\nAbout its working principle, you can refer to this Chinese [article](https://canyie.github.io/2020/04/27/dynamic-hooking-framework-on-art/).\n\nNote: For Android 6.0 devices with arm32/thumb-2 architectures, the arguments may be wrong; and for Android 9.0+, pine will disable the hidden api restriction policy.\n\n~~The name, Pine, represents a class of antipsychotic drugs represented by Quetiapine and Clozapine. It is also an acronym for \"Pine Is Not Epic\".~~\n\n## Usage\n### Basic Usage\n[![Download](https://img.shields.io/maven-central/v/top.canyie.pine/core.svg)](https://repo1.maven.org/maven2/top/canyie/pine/core/)\n\nAdd dependencies in build.gradle (like this):\n```groovy\ndependencies {\n    implementation 'top.canyie.pine:core:\u003cversion\u003e'\n}\n```\nBasic configuration:\n```java\nPineConfig.debug = true; // Do we need to print more detailed logs?\nPineConfig.debuggable = BuildConfig.DEBUG; // Is this process debuggable?\n```\n\nExample 1: monitor the creation of activities\n```java\nPine.hook(Activity.class.getDeclaredMethod(\"onCreate\", Bundle.class), new MethodHook() {\n    @Override public void beforeCall(Pine.CallFrame callFrame) {\n        Log.i(TAG, \"Before \" + callFrame.thisObject + \" onCreate()\");\n    }\n\n    @Override public void afterCall(Pine.CallFrame callFrame) {\n        Log.i(TAG, \"After \" + callFrame.thisObject + \" onCreate()\");\n    }\n});\n```\n\nExample 2: monitor the creation and destroy of all java threads\n```java\nfinal MethodHook runHook = new MethodHook() {\n    @Override public void beforeCall(Pine.CallFrame callFrame) throws Throwable {\n        Log.i(TAG, \"Thread \" + callFrame.thisObject + \" started...\");\n    }\n\n    @Override public void afterCall(Pine.CallFrame callFrame) throws Throwable {\n        Log.i(TAG, \"Thread \" + callFrame.thisObject + \" exit...\");\n    }\n};\n\nPine.hook(Thread.class.getDeclaredMethod(\"start\"), new MethodHook() {\n    @Override public void beforeCall(Pine.CallFrame callFrame) {\n        Pine.hook(ReflectionHelper.getMethod(callFrame.thisObject.getClass(), \"run\"), runHook);\n    }\n});\n```\n\nExample 3: force allow any threads to modify ui:\n```java\nMethod checkThread = Class.forName(\"android.view.ViewRootImpl\").getDeclaredMethod(\"checkThread\");\nPine.hook(checkThread, MethodReplacement.DO_NOTHING);\n```\n\n### Xposed Support\n[![Download](https://img.shields.io/maven-central/v/top.canyie.pine/xposed.svg)](https://repo1.maven.org/maven2/top/canyie/pine/xposed/)\n\nPine supports hooking methods in Xposed-style and loading Xposed modules. (Only java method hooking is supported. Modules using unsupported features like Resource-hooking won't work.)\n```groovy\nimplementation 'top.canyie.pine:xposed:\u003cversion\u003e'\n```\nDirectly hook methods in Xposed-style:\n```java\nXposedHelpers.findAndHookMethod(TextView.class, \"setText\",\n                CharSequence.class, TextView.BufferType.class, boolean.class, int.class,\n                new XC_MethodHook() {\n                    @Override\n                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\n                        Log.e(TAG, \"Before TextView.setText\");\n                        param.args[0] = \"hooked\";\n                    }\n\n                    @Override\n                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {\n                        Log.e(TAG, \"After TextView.setText\");\n                    }\n                });\n```\nor like this:\n```java\nXposedBridge.hookMethod(target, callback);\n```\n\nand you can load xposed modules (resources hook is not supported now):\n```java\n// 1. load modules\nPineXposed.loadModule(new File(modulePath));\n\n// 2. call all 'IXposedHookLoadPackage' callback\nPineXposed.onPackageLoad(packageName, processName, appInfo, isFirstApp, classLoader);\n```\nNote:\n1. Hooks will only take effect in the current process. If you want hooks take effect in other processes, inject your code into them first. There's nothing to do with us.\n2. Modules that use unsupported features (e.g. Resources hook or XSharedPreferences) will not work.\n\n### Enhanced Features\n[![Download](https://img.shields.io/maven-central/v/top.canyie.pine/enhances.svg)](https://repo1.maven.org/maven2/top/canyie/pine/enhances/)\n\nWith [Dobby](https://github.com/jmpews/Dobby), you can use some enhanced features:\n```groovy\nimplementation 'top.canyie.pine:enhances:\u003cversion\u003e'\n```\n\n- Delay hook (aka pending hook) support, hooking static methods without initializing its declaring class immediately:\n```java\nPineEnhances.enableDelayHook();\n```\n\n### ProGuard\nIf you use Xposed features and Xposed APIs need to be called outside your module (e.g. you call `PineXposed.loadModule()` to load external modules):\n```\n# Keep Xposed APIs\n-keep class de.robv.android.xposed.** { *; }\n-keep class android.** { *; }\n```\n\n## Known issues\n- May not be compatible with some devices/systems.\n\n- Due to [#11](https://github.com/canyie/pine/issues/11), we recommend hooking methods with less concurrency as much as possible, for example:\n```java\npublic static void method() {\n    synchronized (sLock) {\n        methodLocked();\n    }\n}\n\nprivate static void methodLocked() {\n    // ...\n}\n```\nIn the example, we recommend you to hook `methodLocked` instead of `method`.\n\n- Pine will disable hidden api policy on initialization by default. Due to an ART bug, if a thread changes hidden api policy while another thread is calling a API that lists members of a class, a out-of-bounds write may occur and causes crashes. We have no way to fix system bugs, so the only way is, initialize our library before other threads is started to avoid the race condition. For more info, see tiann/FreeReflection#60.\n\n- For more, see [issues](https://github.com/canyie/pine/issues).\n\n## Discussion\n[QQ Group：949888394](https://shang.qq.com/wpa/qunwpa?idkey=25549719b948d2aaeb9e579955e39d71768111844b370fcb824d43b9b20e1c04)\n[Telegram Group: @DreamlandFramework](https://t.me/DreamlandFramework)\n\n## Credits\n- [SandHook](https://github.com/ganyao114/SandHook)\n- [Epic](https://github.com/tiann/epic)\n- [AndroidELF](https://github.com/ganyao114/AndroidELF)\n- [FastHook](https://github.com/turing-technician/FastHook)\n- [YAHFA](https://github.com/PAGalaxyLab/YAHFA)\n- [Dobby](https://github.com/jmpews/Dobby)\n- [LSPosed](https://github.com/LSPosed/LSPosed)\n- [libcxx-prefab](https://github.com/RikkaW/libcxx-prefab)\n\n## License\n[Pine](https://github.com/canyie/pine) Copyright (c) [canyie](http://github.com/canyie)\n\n[AndroidELF](https://github.com/ganyao114/AndroidELF)  Copyright (c) [Swift Gan](https://github.com/ganyao114)\n\n[Dobby](https://github.com/jmpews/Dobby)  Copyright (c) [jmpews](https://github.com/jmpews)\n\nLicensed under the Anti 996 License, Version 1.0 (the \"License\");\n\nyou may not use this \"Pine\" project except in compliance with the License.\n\nYou may obtain a copy of the License at\n\nhttps://github.com/996icu/996.ICU/blob/master/LICENSE\n","funding_links":[],"categories":["Java","Java (504)"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcanyie%2Fpine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcanyie%2Fpine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcanyie%2Fpine/lists"}