134 lines
4.8 KiB
Markdown
134 lines
4.8 KiB
Markdown
|
|
## 便携式 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):[下载页面](https://www.azul.com/downloads/?version=java-8-lts&package=jre)
|
|||
|
|
- BellSoft Liberica 8 JRE(Standard/Full,Full 含 JavaFX):[下载页面](https://bell-sw.com/pages/downloads/#/java-8-lts)
|
|||
|
|
- Eclipse Temurin 8 JRE(Adoptium):[下载页面](https://adoptium.net/temurin/releases/?version=8)
|
|||
|
|
|
|||
|
|
选择要点:
|
|||
|
|
- 需要 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 运行工具(开发/生产两种路径):
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
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 };
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
在生命周期中调用(示例):
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
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 或厂商许可证)。
|
|||
|
|
- 建议在应用的“关于/许可证”中附上所选发行版的许可证链接与致谢。
|
|||
|
|
|
|||
|
|
### 常见问题
|
|||
|
|
1) 是否“阉割”?
|
|||
|
|
— 上述 JRE 8 发行版均为标准运行时,通过兼容性测试;JRE 不包含开发者工具属于正常区别,不是删减。
|
|||
|
|
|
|||
|
|
2) 何时需要 JDK 而不是 JRE?
|
|||
|
|
— 需要 `javac` 编译或 `jcmd/jmap` 等诊断工具,或你的 Java 组件依赖 `tools.jar` 时。
|
|||
|
|
|
|||
|
|
3) 体积如何优化?
|
|||
|
|
— 选择 headless(若无 GUI 需求)、去除无用语言/字体包;或改用 JDK 9+ 使用 jlink(不适用于 8)。
|
|||
|
|
|
|||
|
|
|