4.8 KiB
4.8 KiB
便携式 JRE/JDK8 集成指南
本指南介绍如何将 JRE 8 以“便携式”(解压即用、无需安装)的方式随应用打包,并在 Electron 主进程中通过绝对路径调用,从而避免要求用户在系统中安装 JDK/JRE。
为什么选择便携式 JRE
- 无需管理员权限与系统环境变量配置,用户无感知。
- 不污染系统环境(不写入 JAVA_HOME/PATH)。
- 跨平台一致,可精简体积、可控版本。
适用场景
- 运行 Java 程序或 JAR 包(仅需运行时)。
- 不需要 javac/jcmd/jmap 等开发/诊断工具(若需要,请改为随包便携式 JDK)。
推荐的 JRE 8 发行版(可再分发)
- Azul Zulu 8 JRE(可选 ZuluFX 含 JavaFX):下载页面
- BellSoft Liberica 8 JRE(Standard/Full,Full 含 JavaFX):下载页面
- Eclipse Temurin 8 JRE(Adoptium):下载页面
选择要点:
- 需要 AWT/Swing/字体/打印 → 选择非 headless 包。
- 需要 JavaFX → 选择 Liberica Full 或 ZuluFX。
- 仅命令行/服务端 → 任意 JRE 8(headless 也可)。
目录放置约定
将解压后的 JRE 放入项目的 build/extraResources/jre,保证内部存在 bin/java(.exe):
build/
extraResources/
jre/
bin/
java(.exe)
lib/
...
构建后在生产环境可通过 process.resourcesPath 访问:
<app>/resources/extraResources/jre/bin/java(.exe)。
主进程调用示例
在 electron/preload/lifecycle.js 或你的业务模块中封装 Java 运行工具(开发/生产两种路径):
const path = require('path');
const { spawn } = require('child_process');
function getExtraResourcesDir() {
// 开发态:使用项目目录;生产态:使用 asar/resources 目录
const isDev = !!process.env.EE_DEV || process.env.NODE_ENV === 'development';
return isDev
? path.join(process.cwd(), 'build', 'extraResources')
: path.join(process.resourcesPath, 'extraResources');
}
function getJavaBinPath() {
const extraDir = getExtraResourcesDir();
const javaBinName = process.platform === 'win32' ? 'java.exe' : 'java';
return path.join(extraDir, 'jre', 'bin', javaBinName);
}
function runJavaJar(jarAbsPath, args = [], options = {}) {
const javaPath = getJavaBinPath();
const child = spawn(javaPath, ['-jar', jarAbsPath, ...args], {
stdio: 'inherit',
...options,
});
return child;
}
async function ensureJavaVersion(logger) {
return new Promise((resolve) => {
const child = spawn(getJavaBinPath(), ['-version']);
let out = '';
let err = '';
child.stdout && child.stdout.on('data', (d) => (out += d.toString()))
child.stderr && child.stderr.on('data', (d) => (err += d.toString()))
child.on('close', () => {
const text = (out + '\n' + err).trim();
logger && logger.info('[java] version check:', text);
resolve(text.includes('1.8.0'));
});
});
}
module.exports = { getJavaBinPath, runJavaJar, ensureJavaVersion };
在生命周期中调用(示例):
const { logger } = require('ee-core/log');
const path = require('path');
const { runJavaJar, ensureJavaVersion } = require('./java-runner');
class Lifecycle {
async ready() {
const ok = await ensureJavaVersion(logger);
if (!ok) {
logger.error('[java] 未检测到 JRE 8,请检查 extraResources/jre 是否存在');
}
}
async windowReady() {
const jarPath = path.join(process.resourcesPath || process.cwd(), 'extraResources', 'tools', 'your-app.jar');
// 示例:延后在某业务时机再启动 Java 进程
// const proc = runJavaJar(jarPath, ['--arg1', 'value']);
}
}
注意:示例中的 java-runner 为上文工具函数文件,实际请按你的项目结构放置。
验证清单
- 运行
jre/bin/java -version输出包含1.8.0_xxx。 - 若涉及 GUI/字体/打印,验证 AWT/Swing 中文渲染与打印。
- 若需 JavaFX,验证 JavaFX Demo 启动。
- 若涉及 TLS/HTTPS,验证 SSL 通信正常。
许可与合规
- Azul Zulu、Eclipse Temurin(Adoptium)、BellSoft Liberica 的 JRE/JDK 8 发行包均可免费再分发(GPLv2+CE 或厂商许可证)。
- 建议在应用的“关于/许可证”中附上所选发行版的许可证链接与致谢。
常见问题
-
是否“阉割”? — 上述 JRE 8 发行版均为标准运行时,通过兼容性测试;JRE 不包含开发者工具属于正常区别,不是删减。
-
何时需要 JDK 而不是 JRE? — 需要
javac编译或jcmd/jmap等诊断工具,或你的 Java 组件依赖tools.jar时。 -
体积如何优化? — 选择 headless(若无 GUI 需求)、去除无用语言/字体包;或改用 JDK 9+ 使用 jlink(不适用于 8)。