├── .gitignore
├── AndroidManifest.xml
├── README.md
├── ic_launcher-web.png
├── jni
├── Android.mk
├── LinearAllocFix.c
└── LinearAllocFix.h
├── libs
└── armeabi
│ └── liblinear-alloc-fix.so
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── layout
│ └── activity_main.xml
└── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── info
└── viila
└── android
└── linearallocfix
├── app
└── LinearAllocFixApplication.java
├── lib
├── LinearAllocFix.class
└── LinearAllocFix.java
└── ui
└── MainActivity.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | .git
3 | .idea
4 | .project
5 | .settings
6 | bin
7 | gen
8 | obj
9 | *.iml
10 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Hack Dalvik VM解决Android 2.3 DEX/LinearAllocHdr超限 ##
2 |
3 | [link to my blog](http://viila.info/2014/04/android-2-3-dex-max-function-problem/)
4 |
5 | 配合[APKCounter](https://github.com/viilaismonster/ApkFuncCounter)使用更佳
6 |
7 | 当安卓工程庞大到一定程度(代码结构渣到一定程度)的时候,就会遇到诸如最大方法数超过限制导致无法安装,Crash等问题。
8 |
9 | 相关关键词:Android 2.3 INSTALL_FAILED_DEXOPT 65535
10 |
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/ic_launcher-web.png
--------------------------------------------------------------------------------
/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LOCAL_MODULE := linear-alloc-fix
6 | LOCAL_SRC_FILES := LinearAllocFix.c
7 |
8 | LOCAL_LDLIBS := -ldl -llog
9 |
10 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/jni/LinearAllocFix.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "LinearAllocFix.h"
3 | #include
4 | #include
5 | #include
6 |
7 | #define LOG_TAG "*LinearAllocFix*"
8 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
9 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
10 | #define MEMORY_MIN 32768
11 |
12 | #define TARGET_VAL 5*1024*1024
13 | #define HACK_VAL 8*1024*1024
14 |
15 | // copy from https://github.com/android/platform_dalvik/blob/android-2.3.7_r1/vm/LinearAlloc.h#L33
16 | typedef struct LinearAllocHdr {
17 | int curOffset; /* offset where next data goes */
18 | pthread_mutex_t lock; /* controls updates to this struct */
19 |
20 | char* mapAddr; /* start of mmap()ed region */
21 | int mapLength; /* length of region */
22 | int firstOffset; /* for chasing through */
23 |
24 | short* writeRefCount; /* for ENFORCE_READ_ONLY */
25 | } LinearAllocHdr;
26 |
27 | int* hdrMapLength = NULL;
28 | struct LinearAllocHdr* hdr = NULL;
29 |
30 | jint JNI_OnLoad(JavaVM* vm, void* reserved) {
31 |
32 | void** ptr = (void**)MEMORY_MIN;
33 | char* line;
34 | int max = 2*MEMORY_MIN;
35 |
36 | while(max--) {
37 | if(*ptr == (void*)vm) {
38 | line = malloc(100*sizeof(char));
39 | sprintf(line, "find VM %d = %d", ptr, *ptr);
40 | LOGI(line);
41 | free(line);
42 | }
43 | if(*(int*)ptr == TARGET_VAL) {
44 | line = malloc(100*sizeof(char));
45 | sprintf(line, "%d = %d", ptr, *ptr);
46 | LOGE(line);
47 | free(line);
48 | hdrMapLength = (int*)ptr;
49 | hdr = (void*)(ptr-3);
50 | break;
51 | }
52 | ptr++;
53 | }
54 |
55 | if(hdr) {
56 | line = malloc(100*sizeof(char));
57 | sprintf(line, " hdr->curOffset=%d mapLength=%d firstOffset=%d",
58 | hdr->curOffset, hdr->mapLength, hdr->firstOffset);
59 | LOGI(line);
60 | free(line);
61 | }
62 |
63 | return JNI_VERSION_1_4;
64 | }
65 |
66 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_current(
67 | JNIEnv * env,
68 | jobject context) {
69 |
70 | if(!hdrMapLength)
71 | return -1;
72 |
73 | return *hdrMapLength;
74 | }
75 |
76 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_hack(
77 | JNIEnv * env,
78 | jobject context) {
79 |
80 | if(!hdrMapLength)
81 | return -1;
82 |
83 | pthread_mutex_lock(&hdr->lock);
84 |
85 | *hdrMapLength = HACK_VAL;
86 | hdr->mapAddr = mmap(NULL, hdr->mapLength, PROT_READ | PROT_WRITE,
87 | MAP_PRIVATE | MAP_ANON, -1, 0);
88 |
89 | pthread_mutex_unlock(&hdr->lock);
90 |
91 | return *hdrMapLength;
92 | }
93 |
94 |
95 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_debug(
96 | JNIEnv * env,
97 | jobject context,
98 | jint offset, jint attr) {
99 |
100 | return -1;
101 | }
102 |
--------------------------------------------------------------------------------
/jni/LinearAllocFix.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class info_viila_android_linearallocfix_lib_LinearAllocFix */
4 |
5 | #ifndef _Included_info_viila_android_linearallocfix_lib_LinearAllocFix
6 | #define _Included_info_viila_android_linearallocfix_lib_LinearAllocFix
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 |
11 | /*
12 | * Class: info_viila_android_linearallocfix_lib_LinearAllocFix
13 | * Method: current
14 | * Signature: ()I
15 | */
16 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_current
17 | (JNIEnv *, jobject);
18 |
19 | /*
20 | * Class: info_viila_android_linearallocfix_lib_LinearAllocFix
21 | * Method: debug
22 | * Signature: ()I
23 | */
24 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_hack
25 | (JNIEnv *, jobject);
26 |
27 | /*
28 | * Class: info_viila_android_linearallocfix_lib_LinearAllocFix
29 | * Method: hack
30 | * Signature: ()I
31 | */
32 | JNIEXPORT jlong JNICALL Java_info_viila_android_linearallocfix_lib_LinearAllocFix_debug
33 | (JNIEnv *, jobject, jint, jint);
34 |
35 | #ifdef __cplusplus
36 | }
37 | #endif
38 | #endif
39 |
--------------------------------------------------------------------------------
/libs/armeabi/liblinear-alloc-fix.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/libs/armeabi/liblinear-alloc-fix.so
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
17 |
23 |
24 |
30 |
31 |
36 |
37 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | LinearAllocFix
5 | Settings
6 | Hello world!
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/info/viila/android/linearallocfix/app/LinearAllocFixApplication.java:
--------------------------------------------------------------------------------
1 | package info.viila.android.linearallocfix.app;
2 |
3 | import info.viila.android.linearallocfix.lib.LinearAllocFix;
4 | import android.app.Application;
5 |
6 | public class LinearAllocFixApplication extends Application {
7 | public LinearAllocFixApplication() {
8 | // LinearAllocFix.getInstance();
9 | // LinearAllocFix.getInstance().current();
10 | // LinearAllocFix.getInstance().hack();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/info/viila/android/linearallocfix/lib/LinearAllocFix.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/viilaismonster/LinearAllocFix/e496534773a38647e741f6ec4841fd32470d2fb1/src/info/viila/android/linearallocfix/lib/LinearAllocFix.class
--------------------------------------------------------------------------------
/src/info/viila/android/linearallocfix/lib/LinearAllocFix.java:
--------------------------------------------------------------------------------
1 | package info.viila.android.linearallocfix.lib;
2 |
3 | import android.R.integer;
4 |
5 | public class LinearAllocFix {
6 |
7 | private static LinearAllocFix fixer;
8 |
9 | public static LinearAllocFix getInstance() {
10 | if(fixer == null)
11 | fixer = new LinearAllocFix();
12 | return fixer;
13 | }
14 |
15 | private LinearAllocFix() {
16 | System.loadLibrary("linear-alloc-fix");
17 | }
18 |
19 | public native long current();
20 | public native long hack();
21 | public native long debug(int offset, int attr);
22 | }
23 |
--------------------------------------------------------------------------------
/src/info/viila/android/linearallocfix/ui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package info.viila.android.linearallocfix.ui;
2 |
3 | import info.viila.android.linearallocfix.lib.LinearAllocFix;
4 | import android.hardware.Camera;
5 | import android.os.Bundle;
6 | import android.R.integer;
7 | import android.app.Activity;
8 | import android.view.Menu;
9 | import android.view.View;
10 | import android.view.View.OnClickListener;
11 | import android.widget.Button;
12 | import android.widget.LinearLayout;
13 | import android.widget.TextView;
14 |
15 | public class MainActivity extends Activity implements OnClickListener{
16 |
17 | Button btnDump, btnHack, btnClear;
18 | LinearLayout log;
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_main);
23 |
24 | btnDump = (Button)findViewById(R.id.btnDump);
25 | btnHack = (Button)findViewById(R.id.btnHack);
26 | btnClear = (Button)findViewById(R.id.btnClear);
27 | log = (LinearLayout)findViewById(R.id.log);
28 |
29 | btnDump.setOnClickListener(this);
30 | btnHack.setOnClickListener(this);
31 | btnClear.setOnClickListener(this);
32 | Thread tmp;
33 | }
34 |
35 | @Override
36 | public void onClick(View v) {
37 | switch (v.getId()) {
38 | case R.id.btnDump:
39 | int [] attrs = {3};
40 | for(int i = 6; i<= 6;i++) {
41 | StringBuilder sBuilder = new StringBuilder();
42 | for(int j:attrs)
43 | sBuilder.append(LinearAllocFix.getInstance().debug(i, j)+", ");
44 | addLog(i+"="+sBuilder.toString());
45 | }
46 | break;
47 |
48 | case R.id.btnHack:
49 | addLog("current="+LinearAllocFix.getInstance().current()
50 | +"\n"+"hack="+LinearAllocFix.getInstance().hack());
51 | break;
52 |
53 | case R.id.btnClear:
54 | log.removeAllViews();
55 | break;
56 | }
57 | }
58 |
59 | private void addLog(String string) {
60 | TextView text = new TextView(this);
61 | text.setText(string);
62 | log.addView(text, 0);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------