@@ -3,6 +3,10 @@ package org.autojs.autojs.rhino
33import android.os.Build
44import android.util.Log
55import com.android.dx.command.dexer.Main
6+ import com.android.tools.r8.CompilationMode
7+ import com.android.tools.r8.D8
8+ import com.android.tools.r8.D8Command
9+ import com.android.tools.r8.OutputMode
610import dalvik.system.DexClassLoader
711import net.lingala.zip4j.ZipFile
812import net.lingala.zip4j.exception.ZipException
@@ -84,8 +88,18 @@ class AndroidClassLoader(private val parent: ClassLoader, private val cacheDir:
8488 }
8589 }
8690
87- @Throws(IOException ::class )
8891 fun loadJar (file : File ): DexClassLoader {
92+ try {
93+ val dexFile = jarToDex(file, cacheDir)
94+ return loadDex(dexFile)
95+ } catch (e: Exception ) {
96+ Log .e(TAG , " loadJar: failed to load jar ${file.path} " , e)
97+ return loadJar1(file)
98+ }
99+ }
100+
101+ @Throws(IOException ::class )
102+ fun loadJar1 (file : File ): DexClassLoader {
89103 val path = file.path
90104 Log .d(TAG , " loadJar: jar = $path " )
91105 if (! file.exists() || ! file.canRead()) {
@@ -215,6 +229,39 @@ class AndroidClassLoader(private val parent: ClassLoader, private val cacheDir:
215229
216230 private fun generateDexFileName (jar : File ) = md5(" ${jar.path} _${jar.lastModified()} " )
217231
232+ private fun jarToDex (jar : File , cacheDir : File ): File {
233+ val dexName = generateDexFileName(jar)
234+ val dexFile = File (cacheDir, " $dexName .dex" )
235+ if (dexFile.exists()) {
236+ return dexFile
237+ }
238+ val tmpOut = File (cacheDir, " ${dexName} _tmp" ).apply { mkdirs() }
239+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
240+ val cmd = D8Command .builder()
241+ .addProgramFiles(jar.toPath())
242+ .setOutput(tmpOut.toPath(), OutputMode .DexIndexed )
243+ .setMode(CompilationMode .RELEASE )
244+ .build()
245+ D8 .run (cmd)
246+ } else {
247+ val args = arrayOf(
248+ " --output" , tmpOut.absolutePath,
249+ " --release" ,
250+ jar.absolutePath
251+ )
252+ D8 .main(args)
253+ }
254+ val classesDex = File (tmpOut, " classes.dex" )
255+ if (classesDex.exists().not ()) {
256+ throw IOException (" R8 did not produce classes.dex" )
257+ }
258+ if (classesDex.renameTo(dexFile).not ()) {
259+ dexFile.outputStream().use { out -> classesDex.inputStream().use { it.copyTo(out ) } }
260+ }
261+ tmpOut.deleteRecursively()
262+ return dexFile
263+ }
264+
218265 companion object {
219266
220267 private val TAG = AndroidClassLoader ::class .java.simpleName
0 commit comments