-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support multidex feature in plugin application for the ROM below LOLLIPOP #264
Merged
Merged
Changes from 10 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
234e9bb
support multidex feature in plugin application for the ROM below LOLL…
wangfuda 5a3ece7
add lintOptions in library's build.gradle
wangfuda 2b67f45
Merge remote-tracking branch 'upstream/master'
wangfuda 58ef28e
refactor support multidex feature in plugin application for the ROM b…
wangfuda 2b5094e
reset the commit of host-lib's build.gradle
wangfuda 8408773
Refactoring code about getting the DEX section
wangfuda 30c9649
Refactoring code about getting the DEX section
wangfuda 417607a
Refactoring code about the DEX section,again
wangfuda 0ae12d5
remove the move file section of extra dex
wangfuda e30db02
move file or files in dir correctly
wangfuda 9f1f389
delete extra dex files when all the dexes are optimized
wangfuda File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,11 +16,25 @@ | |
|
||
package com.qihoo360.replugin; | ||
|
||
import com.qihoo360.replugin.utils.ReflectUtils; | ||
import android.os.Build; | ||
|
||
import com.qihoo360.replugin.helper.LogDebug; | ||
import com.qihoo360.replugin.model.PluginInfo; | ||
import com.qihoo360.replugin.utils.CloseableUtils; | ||
import com.qihoo360.replugin.utils.FileUtils; | ||
import com.qihoo360.replugin.utils.ReflectUtils; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.lang.reflect.Array; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.Enumeration; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.zip.ZipEntry; | ||
import java.util.zip.ZipFile; | ||
|
||
import dalvik.system.DexClassLoader; | ||
|
||
|
@@ -42,6 +56,7 @@ public class PluginDexClassLoader extends DexClassLoader { | |
/** | ||
* 初始化插件的DexClassLoader的构造函数。插件化框架会调用此函数。 | ||
* | ||
* @param pi the plugin's info,refer to {@link PluginInfo} | ||
* @param dexPath the list of jar/apk files containing classes and | ||
* resources, delimited by {@code File.pathSeparator}, which | ||
* defaults to {@code ":"} on Android | ||
|
@@ -52,8 +67,11 @@ public class PluginDexClassLoader extends DexClassLoader { | |
* {@code null} | ||
* @param parent the parent class loader | ||
*/ | ||
public PluginDexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) { | ||
public PluginDexClassLoader(PluginInfo pi, String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent) { | ||
super(dexPath, optimizedDirectory, librarySearchPath, parent); | ||
|
||
installMultiDexesBeforeLollipop(pi, dexPath, parent); | ||
|
||
mHostClassLoader = RePluginInternal.getAppClassLoader(); | ||
|
||
initMethods(mHostClassLoader); | ||
|
@@ -123,4 +141,198 @@ private Class<?> loadClassFromHost(String className, boolean resolve) throws Cla | |
} | ||
return c; | ||
} | ||
|
||
/** | ||
* install extra dexes | ||
* | ||
* @param pi | ||
* @param dexPath | ||
* @param parent | ||
* @deprecated apply to ROM before Lollipop,may be deprecated | ||
*/ | ||
private void installMultiDexesBeforeLollipop(PluginInfo pi, String dexPath, ClassLoader parent) { | ||
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | ||
return; | ||
} | ||
|
||
try { | ||
|
||
// get paths of extra dex | ||
List<File> dexFiles = getExtraDexFiles(pi, dexPath); | ||
|
||
if (dexFiles != null && dexFiles.size() > 0) { | ||
|
||
List<Object[]> allElements = new LinkedList<>(); | ||
|
||
// get dexElements of main dex | ||
Class<?> clz = Class.forName("dalvik.system.BaseDexClassLoader"); | ||
Object pathList = ReflectUtils.readField(clz, this, "pathList"); | ||
Object[] mainElements = (Object[]) ReflectUtils.readField(pathList.getClass(), pathList, "dexElements"); | ||
allElements.add(mainElements); | ||
|
||
for (File file : dexFiles) { | ||
if (LogDebug.LOG && RePlugin.getConfig().isPrintDetailLog()) { | ||
LogDebug.d(TAG, "dex file:" + file.getName()); | ||
} | ||
|
||
// get dexElements of extra dex (need to load dex first) | ||
String optimizedDirectory = pi.getExtraOdexDir().getAbsolutePath(); | ||
DexClassLoader dexClassLoader = new DexClassLoader(file.getAbsolutePath(), optimizedDirectory, optimizedDirectory, parent); | ||
// delete extra dex, after optimized | ||
FileUtils.forceDelete(pi.getExtraDexDir()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 如果有三个及以上的Dex,直接删除ExtraDir会不会导致第三个Dex无法被优化? 从流程上看:
|
||
|
||
Object obj = ReflectUtils.readField(clz, dexClassLoader, "pathList"); | ||
Object[] dexElements = (Object[]) ReflectUtils.readField(obj.getClass(), obj, "dexElements"); | ||
allElements.add(dexElements); | ||
} | ||
|
||
// combine Elements | ||
Object combineElements = combineArray(allElements); | ||
|
||
// rewrite Elements combined to classLoader | ||
ReflectUtils.writeField(pathList.getClass(), pathList, "dexElements", combineElements); | ||
|
||
//Test whether the Extra Dex is installed | ||
if (LogDebug.LOG && RePlugin.getConfig().isPrintDetailLog()) { | ||
|
||
Object object = ReflectUtils.readField(pathList.getClass(), pathList, "dexElements"); | ||
int length = Array.getLength(object); | ||
LogDebug.d(TAG, "dexElements length:" + length); | ||
} | ||
} | ||
|
||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* combine dexElements Array | ||
* | ||
* @param allElements all dexElements of dexes | ||
* @return the combined dexElements | ||
*/ | ||
private Object combineArray(List<Object[]> allElements) { | ||
|
||
int startIndex = 0; | ||
int arrayLength = 0; | ||
Object[] originalElements = null; | ||
|
||
for (Object[] elements : allElements) { | ||
|
||
if (originalElements == null) { | ||
originalElements = elements; | ||
} | ||
|
||
arrayLength += elements.length; | ||
} | ||
|
||
Object[] combined = (Object[]) Array.newInstance( | ||
originalElements.getClass().getComponentType(), arrayLength); | ||
|
||
for (Object[] elements : allElements) { | ||
|
||
System.arraycopy(elements, 0, combined, startIndex, elements.length); | ||
startIndex += elements.length; | ||
} | ||
|
||
return combined; | ||
} | ||
|
||
/** | ||
* get paths of extra dex | ||
* | ||
* @param pi | ||
* @param dexPath | ||
* @return the File list of the extra dexes | ||
*/ | ||
private List<File> getExtraDexFiles(PluginInfo pi, String dexPath) { | ||
|
||
ZipFile zipFile = null; | ||
List<File> files = null; | ||
|
||
try { | ||
|
||
if (pi != null) { | ||
zipFile = new ZipFile(dexPath); | ||
files = traverseExtraDex(pi, zipFile); | ||
} | ||
|
||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} finally { | ||
CloseableUtils.closeQuietly(zipFile); | ||
} | ||
|
||
return files; | ||
|
||
} | ||
|
||
/** | ||
* traverse extra dex files | ||
* | ||
* @param pi | ||
* @param zipFile | ||
* @return the File list of the extra dexes | ||
*/ | ||
private static List<File> traverseExtraDex(PluginInfo pi, ZipFile zipFile) { | ||
|
||
String dir = null; | ||
List<File> files = new LinkedList<>(); | ||
Enumeration<? extends ZipEntry> entries = zipFile.entries(); | ||
while (entries.hasMoreElements()) { | ||
ZipEntry entry = entries.nextElement(); | ||
String name = entry.getName(); | ||
if (name.contains("../")) { | ||
// 过滤,防止被攻击 | ||
continue; | ||
} | ||
|
||
try { | ||
if (name.contains(".dex") && !name.equals("classes.dex")) { | ||
|
||
if (dir == null) { | ||
dir = pi.getExtraDexDir().getAbsolutePath(); | ||
} | ||
|
||
File file = new File(dir, name); | ||
extractFile(zipFile, entry, file); | ||
files.add(file); | ||
|
||
if (LogDebug.LOG && RePlugin.getConfig().isPrintDetailLog()) { | ||
LogDebug.d(TAG, "dex path:" + file.getAbsolutePath()); | ||
} | ||
} | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
} | ||
|
||
return files; | ||
} | ||
|
||
/** | ||
* extract File | ||
* | ||
* @param zipFile | ||
* @param ze | ||
* @param outFile | ||
* @throws IOException | ||
*/ | ||
private static void extractFile(ZipFile zipFile, ZipEntry ze, File outFile) throws IOException { | ||
InputStream in = null; | ||
try { | ||
in = zipFile.getInputStream(ze); | ||
FileUtils.copyInputStreamToFile(in, outFile); | ||
if (LogDebug.LOG && RePlugin.getConfig().isPrintDetailLog()) { | ||
LogDebug.d(TAG, "extractFile(): Success! fn=" + outFile.getName()); | ||
} | ||
} finally { | ||
CloseableUtils.closeQuietly(in); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里应该在循环外获取,毕竟每次获取的值是一样的。