You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行中的JVM内判断是否可用JDK环境

Detecting if Current JVM is JDK-Bundled JRE (for Liferay Plugin)

Got it, let's solve this problem cleanly—we need to check if the running JVM is part of a full JDK (not a standalone JRE) directly from within the JVM, with external process spawning as a last resort, and implement this in a Liferay plugin to show friendly errors without touching core Liferay code. Here are the most reliable methods:

1. Load JDK-Exclusive Classes (Most Reliable Cross-Version Approach)

The safest in-process method is to attempt loading a class that only exists in the JDK's bundled JRE, not in a standalone JRE. A classic example is com.sun.tools.javac.Main—part of the JDK's development tools but absent in regular JRE distributions.

Here's a reusable code snippet:

public static boolean isRunningOnJdkJre() {
    try {
        // Attempt to load a JDK-only class
        Class.forName("com.sun.tools.javac.Main");
        return true;
    } catch (ClassNotFoundException e) {
        // Class not found = we're on a standalone JRE
        return false;
    }
}

Why this works:

  • Standalone JREs don't include the tools.jar (pre-JDK 9) or the jdk.compiler module (JDK 9+), so these classes won't be available.
  • This runs entirely within the current JVM, no external processes needed—perfect for your plugin's constraints.

2. Check System Properties (Version-Specific Checks)

You can also inspect JVM system properties to infer the environment, though this requires handling JDK 8 and JDK 9+ separately due to modularization:

For JDK 8 and earlier:

Check if java.home points to a subdirectory of a JDK installation, and if sun.boot.class.path includes tools.jar:

public static boolean isJdkJrePre9() {
    String javaHome = System.getProperty("java.home");
    String bootClassPath = System.getProperty("sun.boot.class.path");
    
    // JDK's java.home is typically <jdk>/jre; standalone JRE's is just <jre>
    boolean isJdkSubdir = javaHome.contains(File.separator + "jdk") || javaHome.endsWith(File.separator + "jre");
    boolean hasToolsJar = bootClassPath.contains("tools.jar");
    
    return isJdkSubdir && hasToolsJar;
}

For JDK 9 and later:

Check if the jdk.compiler module is available (standalone JREs exclude development modules):

public static boolean isJdkJrePost9() {
    try {
        ModuleLayer.boot().findModule("jdk.compiler");
        return true;
    } catch (Exception e) {
        return false;
    }
}

Combine both checks for full cross-version coverage.

3. Fallback: Execute External Process (If Needed)

If the above methods don't cover your edge cases, you can fall back to checking if javac is available via a lightweight process spawn. This is less ideal but acceptable as a last option:

public static boolean hasJavacAvailable() {
    try {
        Process process = new ProcessBuilder("javac", "-version").start();
        int exitCode = process.waitFor();
        return exitCode == 0;
    } catch (IOException | InterruptedException e) {
        // javac not found or process failed = standalone JRE
        return false;
    }
}

Implementing in Liferay Plugin

To add friendly error handling in your plugin:

  • Use a PortalLifecycleListener to run the check during Liferay's startup phase.
  • If the check fails, log a clear error and optionally show an alert for portal admins.

Example listener snippet:

@Component(immediate = true)
public class JdkCheckLifecycleListener implements PortalLifecycleListener {

    @Override
    public void portalLifecycleEvent(PortalLifecycleEvent event) {
        if (event.getLifecycle() == PortalLifecycle.PRE_INIT) {
            if (!isRunningOnJdkJre()) {
                _log.error("ERROR: Liferay requires a JDK-bundled JRE to run correctly. Please switch to a full JDK installation.");
                // Optionally add a visible alert for admins
                addAdminAlert("Critical JRE Issue", "Liferay must run on a JDK-bundled JRE. Please update your runtime environment.");
            }
        }
    }

    // Include the isRunningOnJdkJre() method from above here

    private static final Log _log = LogFactoryUtil.getLog(JdkCheckLifecycleListener.class);
}

This approach gives you a clean, in-process check that works across JDK versions, requires no core code changes, and provides clear feedback to users running the wrong runtime.

内容的提问来源于stack exchange,提问作者Olaf Kock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:16:27