Fix the inspectJvmOptions startup check patch by Benjamin Lerer; reviewed by Andrés de la Peña for CASSANDRA-14112
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/b800f3c7 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/b800f3c7 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/b800f3c7 Branch: refs/heads/cassandra-3.0 Commit: b800f3c768289268193b0dd716be99a33f306dad Parents: 35e6d61 Author: Benjamin Lerer <b.le...@gmail.com> Authored: Thu Dec 14 14:52:18 2017 +0100 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Thu Dec 14 14:52:18 2017 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/service/StartupChecks.java | 33 +----- .../org/apache/cassandra/utils/JavaUtils.java | 115 +++++++++++++++++++ .../apache/cassandra/utils/JavaUtilsTest.java | 52 +++++++++ 4 files changed, 170 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/b800f3c7/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 33fd264..266ed14 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.2.12 + * Fix the inspectJvmOptions startup check (CASSANDRA-14112) * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801) * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006) * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873) http://git-wip-us.apache.org/repos/asf/cassandra/blob/b800f3c7/src/java/org/apache/cassandra/service/StartupChecks.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/StartupChecks.java b/src/java/org/apache/cassandra/service/StartupChecks.java index 7ec16d1..f74d3da 100644 --- a/src/java/org/apache/cassandra/service/StartupChecks.java +++ b/src/java/org/apache/cassandra/service/StartupChecks.java @@ -182,7 +182,7 @@ public class StartupChecks } else { - checkOutOfMemoryHandling(); + checkOutOfMemoryHandling(); } } @@ -191,13 +191,7 @@ public class StartupChecks */ private void checkOutOfMemoryHandling() { - int version = getJavaVersion(); - int update = getUpdate(); - // The ExitOnOutOfMemory and CrashOnOutOfMemory are supported since the version 7u101 and 8u92 - boolean jreSupportExitOnOutOfMemory = version > 8 - || (version == 7 && update >= 101) - || (version == 8 && update >= 92); - if (jreSupportExitOnOutOfMemory) + if (JavaUtils.supportExitOnOutOfMemory(System.getProperty("java.version"))) { if (!jvmOptionsContainsOneOf("-XX:OnOutOfMemoryError=", "-XX:+ExitOnOutOfMemoryError", "-XX:+CrashOnOutOfMemoryError")) logger.warn("The JVM is not configured to stop on OutOfMemoryError which can cause data corruption." @@ -214,29 +208,6 @@ public class StartupChecks } /** - * Returns the java version number for an Oracle JVM. - * @return the java version number - */ - private int getJavaVersion() - { - String jreVersion = System.getProperty("java.version"); - String version = jreVersion.startsWith("1.") ? jreVersion.substring(2, 3) // Pre 9 version - : jreVersion.substring(0, jreVersion.indexOf('.')); - return Integer.parseInt(version); - } - - /** - * Return the update number for an Oracle JVM. - * @return the update number - */ - private int getUpdate() - { - String jreVersion = System.getProperty("java.version"); - int updateSeparatorIndex = jreVersion.indexOf('_'); - return Integer.parseInt(jreVersion.substring(updateSeparatorIndex + 1)); - } - - /** * Checks if one of the specified options is being used. * @param optionNames The name of the options to check * @return {@code true} if one of the specified options is being used, {@code false} otherwise. http://git-wip-us.apache.org/repos/asf/cassandra/blob/b800f3c7/src/java/org/apache/cassandra/utils/JavaUtils.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/utils/JavaUtils.java b/src/java/org/apache/cassandra/utils/JavaUtils.java new file mode 100644 index 0000000..f33b8be --- /dev/null +++ b/src/java/org/apache/cassandra/utils/JavaUtils.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility method to retrieve information about the JRE. + */ +public final class JavaUtils +{ + private static final Logger logger = LoggerFactory.getLogger(JavaUtils.class); + + /** + * Checks if the specified JRE support ExitOnOutOfMemory and CrashOnOutOfMemory. + * @param jreVersion the JRE version + * @return {@code true} if the running JRE support ExitOnOutOfMemory and CrashOnOutOfMemory or if the exact version + * cannot be determined, {@code false} otherwise. + */ + public static boolean supportExitOnOutOfMemory(String jreVersion) + { + try + { + int version = parseJavaVersion(jreVersion); + + if (version > 8) + return true; + + int update = parseUpdateForPre9Versions(jreVersion); + // The ExitOnOutOfMemory and CrashOnOutOfMemory are supported since the version 7u101 and 8u92 + return (version == 7 && update >= 101) || (version == 8 && update >= 92); + } + catch (Exception e) + { + logger.error("Some JRE information could not be retrieved for the JRE version: " + jreVersion, e); + // We will continue assuming that the version supports ExitOnOutOfMemory and CrashOnOutOfMemory. + return true; + } + } + + /** + * Parses an Oracle JRE Version to extract the java version number. + * <p> The parsing rules are based on the following + * <a href='http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html'>String Naming Convention</a> and + * <a href='http://openjdk.java.net/jeps/223'>JEP 223: New Version-String Scheme</a>.</p> + * @param jreVersion the Oracle JRE Version + * @return the java version number + * @throws NumberFormatException if the version cannot be retrieved + */ + private static int parseJavaVersion(String jreVersion) + { + String version; + if (jreVersion.startsWith("1.")) + { + version = jreVersion.substring(2, 3); // Pre 9 version + } + else + { + // Version > = 9 + int index = jreVersion.indexOf('.'); + + if (index < 0) + { + // Does not have a minor version so we need to check for EA release + index = jreVersion.indexOf('-'); + if (index < 0) + index = jreVersion.length(); + } + version = jreVersion.substring(0, index); + } + return Integer.parseInt(version); + } + + /** + * Parses an Oracle JRE Version < 9 to extract the update version. + * <p> The parsing rules are based on the following + * <a href='http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html'>String Naming Convention</a>.</p> + * @param jreVersion the Oracle JRE Version + * @return the update version + * @throws NumberFormatException if the update cannot be retrieved + */ + private static int parseUpdateForPre9Versions(String jreVersion) + { + // Handle non GA versions + int dashSeparatorIndex = jreVersion.indexOf('-'); + if (dashSeparatorIndex > 0) + jreVersion = jreVersion.substring(0, dashSeparatorIndex); + + int updateSeparatorIndex = jreVersion.indexOf('_'); + if (updateSeparatorIndex < 0) + return 0; // Initial release + + return Integer.parseInt(jreVersion.substring(updateSeparatorIndex + 1)); + } + + private JavaUtils() + { + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/b800f3c7/test/unit/org/apache/cassandra/utils/JavaUtilsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/utils/JavaUtilsTest.java b/test/unit/org/apache/cassandra/utils/JavaUtilsTest.java new file mode 100644 index 0000000..d704781 --- /dev/null +++ b/test/unit/org/apache/cassandra/utils/JavaUtilsTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.utils; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class JavaUtilsTest +{ + @Test + public void testSupportExitOnOutOfMemory() + { + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.7.0-ea")); // Early Access + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.7.0")); // Major (GA) + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.7.0_20")); // Minor #1 (GA) + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.7.0_5")); // Security #1 (GA) + + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.7.0_95")); + assertTrue(JavaUtils.supportExitOnOutOfMemory("1.7.0_101")); + + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.8.0-ea")); // Early Access + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.8.0")); // Major (GA) + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.8.0_20")); // Minor #1 (GA) + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.8.0_5")); // Security #1 (GA) + + assertFalse(JavaUtils.supportExitOnOutOfMemory("1.8.0_91")); + assertTrue(JavaUtils.supportExitOnOutOfMemory("1.8.0_92")); + assertTrue(JavaUtils.supportExitOnOutOfMemory("1.8.0_101")); + + // Test based on http://openjdk.java.net/jeps/223 + assertTrue(JavaUtils.supportExitOnOutOfMemory("9-ea")); // Early Access + assertTrue(JavaUtils.supportExitOnOutOfMemory("9")); // Major (GA) + assertTrue(JavaUtils.supportExitOnOutOfMemory("9.1.2")); // Minor #1 (GA) + assertTrue(JavaUtils.supportExitOnOutOfMemory("9.0.1")); // Security #1 (GA) + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org