content: package com.antfortune.freeline.util;
  
  import android.os.Build.VERSION;
  import android.util.Log;
  
  import dalvik.system.DexClassLoader;
  import dalvik.system.DexFile;
  import dalvik.system.PathClassLoader;
  
  import java.io.File;
  import java.lang.reflect.Array;
  import java.lang.reflect.Field;
  
  public class DexUtils {
  
      private static final String TAG = "Freeline.hackDex";
  
      public static boolean inject(PathClassLoader classLoader, File dex, File opt) {
          Log.i(TAG, dex.getAbsolutePath() + " dex length: " + dex.length());
          Log.i(TAG, opt.getAbsolutePath() + " opt length: " + opt.length());
  
          DexFile[] dexFiles = null;
          Field pathListField = null;
          Field fDexElements = null;
          Object dstObject = null;
  
          try {
              Object newDexElements;
              int dexLength;
              if (VERSION.SDK_INT >= 14) {
                  pathListField = ReflectUtil.fieldGetOrg(classLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
                  fDexElements = ReflectUtil.fieldGetOrg(pathListField.get(classLoader), "dexElements");
                  Object e = fDexElements.get(pathListField.get(classLoader));
                  dstObject = e;
                  dexFiles = new DexFile[Array.getLength(e)];
                  for (int i = 0; i < Array.getLength(e); ++i) {
                      newDexElements = Array.get(e, i);
                      dexFiles[i] = (DexFile) ReflectUtil.fieldGet(newDexElements, "dexFile");
                  }
              } else {
                  pathListField = ReflectUtil.fieldGetOrg(classLoader, "mDexs");
                  dstObject = pathListField.get(classLoader);
                  dexFiles = new DexFile[Array.getLength(dstObject)];
                  for (dexLength = 0; dexLength < Array.getLength(dstObject); ++dexLength) {
                      dexFiles[dexLength] = (DexFile) Array.get(dstObject, dexLength);
                  }
              }
              dexLength = Array.getLength(dstObject) + 1;
              newDexElements = Array.newInstance(fDexElements.getType().getComponentType(), dexLength);
  
              DexClassLoader dynamicDex = new DexClassLoader(dex.getAbsolutePath(), opt.getAbsolutePath(), null, classLoader.getParent());
              Log.i(TAG, "after opt, dex len:" + dex.length() + "; opt len:" + opt.length());
              Object pathList = pathListField.get(dynamicDex);
              Object dexElements = fDexElements.get(pathList);
              Object firstDexElement = Array.get(dexElements, 0);
              Array.set(newDexElements, 0, firstDexElement);
  
              for (int i = 0; i < dexLength - 1; ++i) {
                  Object element = Array.get(dstObject, i);
                  Array.set(newDexElements, i + 1, element);
              }
  
              if (VERSION.SDK_INT >= 14) {
                  fDexElements.set(pathListField.get(classLoader), newDexElements);
              } else {
                  pathListField.set(classLoader, newDexElements);
              }
              return true;
          } catch (Exception e) {
              Log.e(TAG, "fail to override classloader " + classLoader + " with " + dex.getAbsolutePath(), e);
              return false;
          }
      }
  
  
  }
  