diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/LooperHelper.java b/autojs/src/main/java/com/stardust/autojs/core/looper/LooperHelper.java index 40e329e6..96b3d688 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/LooperHelper.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/LooperHelper.java @@ -1,7 +1,10 @@ package com.stardust.autojs.core.looper; +import android.os.Build; import android.os.Looper; +import androidx.annotation.RequiresApi; + import java.util.concurrent.ConcurrentHashMap; /** diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java index c7cd424f..b44b6d1e 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java @@ -173,6 +173,7 @@ public class Loopers implements MessageQueue.IdleHandler { public void recycle() { quitServantLooper(); mMainMessageQueue.removeIdleHandler(this); + removeThreadLocalValue(); } public void setMainLooperQuitHandler(LooperQuitHandler mainLooperQuitHandler) { @@ -195,11 +196,19 @@ public class Loopers implements MessageQueue.IdleHandler { Log.d(LOG_TAG, "looper queueIdle: " + l); if (shouldQuitLooper()) { l.quit(); + removeThreadLocalValue(); } } return true; } + private void removeThreadLocalValue() { + maxWaitId.remove(); + waitIds.remove(); + looperQuitHandlers.remove(); + maxWaitId.remove(); + } + public void prepare() { if (Looper.myLooper() == null) LooperHelper.prepare(); diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java index 61dbc7e7..cb526b6c 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java @@ -10,6 +10,8 @@ import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.concurrent.VolatileBox; import com.stardust.lang.ThreadCompat; +import org.mozilla.javascript.Context; + import java.util.concurrent.ConcurrentHashMap; /** @@ -37,12 +39,12 @@ public class TimerThread extends ThreadCompat { @Override public void run() { mRuntime.loopers.prepare(); - mTimer = new Timer(mRuntime, mMaxCallbackUptimeMillisForAllThreads); - sTimerMap.put(Thread.currentThread(), mTimer); - ((RhinoJavaScriptEngine) mRuntime.engines.myEngine()).enterContext(); + Context engineContext = ((RhinoJavaScriptEngine) mRuntime.engines.myEngine()).enterContext(); notifyRunning(); new Handler().post(mTarget); try { + mTimer = new Timer(mRuntime, mMaxCallbackUptimeMillisForAllThreads); + sTimerMap.put(Thread.currentThread(), mTimer); Looper.loop(); } catch (Throwable e) { if (!ScriptInterruptedException.causedByInterrupted(e)) { @@ -50,9 +52,9 @@ public class TimerThread extends ThreadCompat { } } finally { onExit(); - mTimer = null; - org.mozilla.javascript.Context.exit(); + ((RhinoJavaScriptEngine)mRuntime.engines.myEngine()).exitContext(engineContext); sTimerMap.remove(Thread.currentThread(), mTimer); + mTimer = null; } } @@ -72,6 +74,7 @@ public class TimerThread extends ThreadCompat { @CallSuper protected void onExit() { mRuntime.loopers.notifyThreadExit(this); + LooperHelper.quitForThread(this); } public static Timer getTimerForThread(Thread thread) { diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt index bdc1edc0..9af22453 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.kt @@ -12,7 +12,10 @@ import com.stardust.autojs.runtime.ScriptRuntime import com.stardust.autojs.script.JavaScriptSource import com.stardust.automator.UiObjectCollection import com.stardust.pio.UncheckedIOException -import org.mozilla.javascript.* +import org.mozilla.javascript.Context +import org.mozilla.javascript.Script +import org.mozilla.javascript.Scriptable +import org.mozilla.javascript.ScriptableObject import org.mozilla.javascript.commonjs.module.RequireBuilder import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider import java.io.File @@ -153,6 +156,15 @@ open class RhinoJavaScriptEngine(private val mAndroidContext: android.content.Co return context } + fun exitContext(context: Context) { + sContextEngineMap.remove(context) + try { + Context.exit() + } catch (e: Exception) { + // do nothing + } + } + protected fun setupContext(context: Context) { context.optimizationLevel = -1 context.languageVersion = Context.VERSION_ES6 diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java b/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java index 4bf4dbf0..7674ff17 100644 --- a/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java +++ b/autojs/src/main/java/com/stardust/autojs/rhino/AndroidClassLoader.java @@ -53,7 +53,9 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa mCacheDir = dir; mLibsDir = new File(dir, "libs"); if (dir.exists()) { - PFiles.deleteFilesOfDir(dir); + if (!(parent instanceof AndroidClassLoader)) { + PFiles.deleteFilesOfDir(dir); + } } else { dir.mkdirs(); } @@ -136,6 +138,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa if (!file.exists()) { throw new FileNotFoundException(file.getPath()); } + Log.d(LOG_TAG, "dex file size: " + file.length()); DexClassLoader loader = new DexClassLoader(file.getPath(), mCacheDir.getPath(), mLibsDir.getPath(), parent); // 根据dex文件名 移除已有的,使得最新载入的在LinkedHashMap末尾 mDexClassLoaders.remove(file.getName()); @@ -167,6 +170,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa arguments.outName = dexFile.getPath(); arguments.jarOutput = true; Main.run(arguments); + Log.d(LOG_TAG, "dex file size: " + dexFile.length()); DexClassLoader loader = loadDex(dexFile); if (isTmpDex) { Log.d(LOG_TAG, "delete tmpFile on finalize:" + dexFile.getName());