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 &lt; 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

Reply via email to