All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.deephaven.server.runner.SafetyChecks Maven / Gradle / Ivy

The newest version!
//
// Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending
//
package io.deephaven.server.runner;

import java.lang.Runtime.Version;
import java.lang.management.ManagementFactory;
import java.util.List;

/**
 * Deephaven safety checks.
 */
public final class SafetyChecks {
    public static final String SAFETY_CHECKS_PROPERTY = "deephaven.safetyChecks";
    public static final String SAFETY_CHECKS_ENV = "DEEPHAVEN_SAFETY_CHECKS";

    /**
     * Checks whether safety checks are enabled. This parses the system property {@value SAFETY_CHECKS_PROPERTY} if it
     * exists, otherwise it parses the environment variable {@value SAFETY_CHECKS_ENV} if it exists, otherwise defaults
     * to {@code true}. Disabling safety checks is not recommended.
     *
     * @return if safety checks are enabled.
     */
    public static boolean isEnabled() {
        return parseBoolean(SAFETY_CHECKS_PROPERTY, SAFETY_CHECKS_ENV, true);
    }

    /**
     * Applies a set of safety checks if {@link #isEnabled()}.
     *
     * @see JDK_8287432
     */
    public static void check() {
        if (!isEnabled()) {
            return;
        }
        JDK_8287432.check();
    }

    private static boolean isEnabled(Class clazz) {
        return parseBoolean(safetyCheckPropertyName(clazz), safetyCheckEnvironmentName(clazz), true);
    }

    private static String safetyCheckEnvironmentName(Class clazz) {
        return "DEEPHAVEN_SAFETY_CHECK_" + clazz.getSimpleName();
    }

    private static String safetyCheckPropertyName(Class clazz) {
        return "deephaven.safetyCheck." + clazz.getSimpleName();
    }

    private static boolean parseBoolean(String propertyName, String envName, boolean defaultValue) {
        final String propertyValue = System.getProperty(propertyName);
        if (propertyValue != null) {
            return Boolean.parseBoolean(propertyValue);
        }
        final String envValue = System.getenv(envName);
        if (envValue != null) {
            return Boolean.parseBoolean(envValue);
        }
        return defaultValue;
    }

    private static String disableSafetyCheckMessage(Class clazz) {
        return String.format(
                "To disable this safety check (not recommended), you can set the system property `-D%s=false` or environment variable `%s=false`.",
                safetyCheckPropertyName(clazz), safetyCheckEnvironmentName(clazz));
    }

    private static String disableSafetyChecksMessage() {
        return String.format(
                "To disable all safety checks (not recommended), you can set the system property `-D%s=false` or environment variable `%s=false`.",
                SAFETY_CHECKS_PROPERTY, SAFETY_CHECKS_ENV);
    }

    private static IllegalStateException exception(Class clazz, String baseMessage) {
        return new IllegalStateException(String.format(
                "%s %s %s",
                baseMessage,
                disableSafetyCheckMessage(clazz),
                disableSafetyChecksMessage()));
    }

    /**
     * A safety check for JDK-8287432.
     */
    public static final class JDK_8287432 {

        private static void check() {
            if (!isEnabled(JDK_8287432.class)) {
                return;
            }
            if (isVulnerableVersion() && !hasWorkaround()) {
                throw exception(JDK_8287432.class, String.format(
                        "The current JDK %s (located at %s) is vulnerable to the bug https://bugs.openjdk.org/browse/JDK-8287432. We recommend updating to 11.0.17+, 17.0.5+, or 21+. If that is not possible, you can apply a workaround '%s'.",
                        Runtime.version(),
                        System.getProperty("java.home"),
                        String.join(" ", workaroundJvmArguments())));
            }
        }

        private static boolean isVulnerableVersion(Version version) {
            switch (version.feature()) {
                case 11:
                    return version.compareTo(Version.parse("11.0.17")) < 0;
                case 17:
                    return version.compareTo(Version.parse("17.0.5")) < 0;
            }
            // Assume the version does not have the bug.
            return false;
        }

        private static boolean isVulnerableVersion() {
            return isVulnerableVersion(Runtime.version());
        }

        private static boolean hasWorkaround() {
            return ManagementFactory.getRuntimeMXBean().getInputArguments()
                    .contains("-XX:DisableIntrinsic=_currentThread");
        }

        private static List workaroundJvmArguments() {
            return List.of("-XX:+UnlockDiagnosticVMOptions", "-XX:DisableIntrinsic=_currentThread");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy