JavaCompileEngine
在Android上面编译和运行Java代码的引擎
Install / Use
/learn @xiaoyvyv/JavaCompileEngineREADME
JavaCompileEngine (支持 JDK8 语法)
这是一个能够在 Android 平台上面编译和运行 Java 代码的引擎,支持 JDK8 语法编译运行。
运行原理:
1、将
*.java文件编译为*.class类文件。 2、通过R8 | D8工具将*.class文件编译为Android平台能够运行的*.dex文件。这一步可以脱糖,可以在安卓平台运行JDK高版本的语法糖,其内部实现基本上还是语法糖转换成了低版本兼容的代码。 3、将*.dex文件通过DexClassLoader加载到应用程序中,并寻找main方法反射调用。 4、代理系统的输入System.in和输出System.out。
示例下载
截图预览
| | | |
|:--|:--|:--|
|
|
|
|
1、引入依赖
第一步:在Project的build.gradle内添加jitpack.io仓库
allprojects {
repositories {
//...
mavenCentral()
}
}
第二步:添加依赖
dependencies {
//...
// 这个依赖比较大(9M 左右),因为内部(assets)包含了一个精简的 Jre,你可以自己选择去除或精简。
implementation 'io.github.xiaoyvyv:compiler-d8:<maven-version>'
}
2、初始化
在你的 Application 的 onCreate 中初始化库。
class App : Application() {
override fun onCreate() {
super.onCreate()
// init
JavaEngine.init(this)
}
}
3、编译 Java 文件
JavaClassCompiler 提供了相关的方法,具体请查阅 JavaClassCompiler.kt。
注意该方法需要配合协程使用,在协程的作用域内调用
// 编译 class,libFolder 为第三方 jar 存放目录,没有传空即可
// 编译完成返回目标 classes.jar,内部通过协程在 IO 线程处理的
val compileJar: File = JavaEngine.classCompiler.compile(
sourceFileOrDir = javaFilePath,
buildDir = buildDir,
libFolder = null
) { taskName, progress ->
// 这里是进度,回调在主线程...
}
4、转换 class文件 到 dex文件
DexCompiler 提供了相关的方法,具体请查阅 JavaDexCompiler.kt
注意该方法需要配合协程使用,在协程的作用域内调用
// 编译 classes.dex,这一步相关的信息通过 System.xxx.print 输出
val dexFile = JavaEngine.dexCompiler.compile(compileJar.absolutePath, buildDir)
5、运行 dex文件
JavaProgram.kt 提供了相关的方法,具体请查阅 JavaProgram.kt
注意 chooseMainClassToRun 默认实现是选中匹配到的第一个 main 方法进行运行,你可以自己在该方法回调内去选择需要执行的的指定某个类。
- chooseMainClassToRun 第一个回调参数:匹配到的包含
main方法的类 - chooseMainClassToRun 第二个回调参数:协程相关的回调,需要将选择的类回调回去
<font color="#ff0000">注意:chooseMainClassToRun 回调会使内部协程一直挂起,你应该及时的通过 continuation.resume() 或 resume.resumeWithException() 让内部知道处理结果,禁止忽略 continuation 的回调,否则会在后台一直占用资源</font>
chooseMainClassToRun、printOut、printErr 回调均在主线程,可以进行 UI 操作。
run 方法运行完成(并不代表程序执行完成,例如你的代码启动了其他线程)会返回一个 programConsole 句柄,可以用于关闭输入输出流。
注意该方法需要配合协程使用,在协程的作用域内调用
// JavaEngine.
val programConsole = JavaEngine.javaProgram.run(dexFile, arrayOf("args"),
chooseMainClassToRun = { classes, continuation ->
val dialog = AlertDialog.Builder(this@CompileActivity)
.setTitle("请选择一个主函数运行")
.setItems(classes.toTypedArray()) { p0, p1 ->
p0.dismiss()
continuation.resume(classes[p1])
}
.setCancelable(false)
.setNegativeButton("取消") { d, v ->
d.dismiss()
continuation.resumeWithException(Exception("取消操作"))
}.create()
dialog.show()
dialog.setCanceledOnTouchOutside(false)
},
printOut = {
binding.printView.append(it)
},
printErr = {
binding.printView.append(it)
})
6、输入数据 如 Scanner等等的处理
直接调用 programConsole. 的 inputStdin(String stdin) 方法即可输入数据。
programConsole.inputStdin(str)
7、编译相关设置
JavaEngine.compilerSetting 提供了相关配置。JavaEngineSetting.kt
8、问题
更多内容请查阅 Demo 和源码 compiler-d8
9、反馈
QQEmail:1223414335@qq.com
Related Skills
node-connect
343.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
90.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
