Skip to content

Commit 99a7ea5

Browse files
[7.4 backport] Add warnings for potential ergonomics failures for JDK8/Windows (#49043)
* Warn when MaxDirectMemorySize may be incorrect (Windows/JDK8 only issue) (#48365) Our JVM ergonomics extract max heap size from JDK PrintFlagsFinal output. On JDK 8, there is a system-dependent bug where memory sizes are cast to 32-bit integers. On affected systems (namely, Windows), when 1/4 of physical memory is more than the maximum integer value, the output of PrintFlagsFinal will be inaccurate. In the pathological case, where the max heap size would be a multiple of 4g, the test will fail. The practical effect of this bug, beyond test failures, is that we may set MaxDirectMemorySize to an incorrect value on Windows. This commit adds a warning about this situation during startup. On 7.4, we also warn for io.netty.allocator.type. * Don't drop user's MaxDirectMemorySize flag on jdk8/windows (#48657) * Always pass user-specified MaxDirectMemorySize We had been testing whether a user had passed a value for MaxDirectMemorySize by parsing the output of "java -XX:PrintFlagsFinal -version". If MaxDirectMemorySize equals zero, we set it to half of max heap. The problem is that on Windows with JDK 8, a JDK bug incorrectly truncates values over 4g and returns multiples of 4g as zero. In order to always respect the user-defined settings, we need to check our input to see if an "-XX:MaxDirectMemorySize" value has been passed. * Always warn for Windows/jdk8 ergo issue Even if a user has set MaxDirectMemorySize, they aren't future-proof for this JDK bug. With this change, we issue a general warning for the windows/JDK8 issue, and a specific warning if MaxDirectMemorySize is unset. * Adjust warning for io.netty.allocator.type
1 parent 2b9d4c7 commit 99a7ea5

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

distribution/tools/launchers/src/main/java/org/elasticsearch/tools/launchers/JvmErgonomics.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.tools.launchers;
2121

22+
import org.elasticsearch.tools.java_version_checker.JavaVersion;
23+
2224
import java.io.BufferedReader;
2325
import java.io.IOException;
2426
import java.io.InputStream;
@@ -57,15 +59,32 @@ static List<String> choose(final List<String> userDefinedJvmOptions) throws Inte
5759
final Map<String, Optional<String>> finalJvmOptions = finalJvmOptions(userDefinedJvmOptions);
5860
final long heapSize = extractHeapSize(finalJvmOptions);
5961
final Map<String, String> systemProperties = extractSystemProperties(userDefinedJvmOptions);
62+
63+
if (System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8) {
64+
Launchers.errPrintln("Warning: with JDK 8 on Windows, Elasticsearch may be unable to derive correct");
65+
Launchers.errPrintln(" ergonomic settings due to a JDK issue (JDK-8074459). Please use a newer");
66+
Launchers.errPrintln(" version of Java.");
67+
}
68+
6069
if (systemProperties.containsKey("io.netty.allocator.type") == false) {
70+
if (System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8) {
71+
Launchers.errPrintln("Warning: io.netty.allocator.type may have been miscalculated due to JDK-8074459.");
72+
Launchers.errPrintln(" Please use a newer version of Java or set io.netty.allocator.type explicitly");
73+
}
6174
if (heapSize <= 1 << 30) {
6275
ergonomicChoices.add("-Dio.netty.allocator.type=unpooled");
6376
} else {
6477
ergonomicChoices.add("-Dio.netty.allocator.type=pooled");
6578
}
6679
}
6780
final long maxDirectMemorySize = extractMaxDirectMemorySize(finalJvmOptions);
68-
if (maxDirectMemorySize == 0) {
81+
if (maxDirectMemorySize == 0 && userDefinedJvmOptions.stream().noneMatch(s -> s.startsWith("-XX:MaxDirectMemorySize"))) {
82+
83+
if (System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8) {
84+
Launchers.errPrintln("Warning: MaxDirectMemorySize may have been miscalculated due to JDK-8074459.");
85+
Launchers.errPrintln(" Please use a newer version of Java or set MaxDirectMemorySize explicitly.");
86+
}
87+
6988
ergonomicChoices.add("-XX:MaxDirectMemorySize=" + heapSize / 2);
7089
}
7190
return ergonomicChoices;

distribution/tools/launchers/src/test/java/org/elasticsearch/tools/launchers/JvmErgonomicsTests.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.Arrays;
2626
import java.util.Collections;
2727
import java.util.HashMap;
28+
import java.util.List;
2829
import java.util.Map;
2930

3031
import static org.hamcrest.Matchers.anyOf;
@@ -56,8 +57,8 @@ public void testExtractValidHeapSizeUsingMaxHeapSize() throws InterruptedExcepti
5657
}
5758

5859
public void testExtractValidHeapSizeNoOptionPresent() throws InterruptedException, IOException {
59-
// Muting on Windows, awaitsfix: https://github.com/elastic/elasticsearch/issues/47384
60-
assumeFalse(System.getProperty("os.name").startsWith("Windows"));
60+
// Muted for jdk8/Windows, see: https://github.com/elastic/elasticsearch/issues/47384
61+
assumeFalse(System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8);
6162
assertThat(
6263
JvmErgonomics.extractHeapSize(JvmErgonomics.finalJvmOptions(Collections.emptyList())),
6364
greaterThan(0L));
@@ -132,6 +133,7 @@ public void testPooledMemoryChoiceOnSmallHeap() throws InterruptedException, IOE
132133
}
133134

134135
public void testPooledMemoryChoiceOnNotSmallHeap() throws InterruptedException, IOException {
136+
// Muted for jdk8/Windows, see: https://github.com/elastic/elasticsearch/issues/47384
135137
assumeFalse(System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8);
136138
final String largeHeap = randomFrom(Arrays.asList("1025M", "2048M", "2G", "8G"));
137139
assertThat(
@@ -140,6 +142,7 @@ public void testPooledMemoryChoiceOnNotSmallHeap() throws InterruptedException,
140142
}
141143

142144
public void testMaxDirectMemorySizeChoice() throws InterruptedException, IOException {
145+
// Muted for jdk8/Windows, see: https://github.com/elastic/elasticsearch/issues/47384
143146
assumeFalse(System.getProperty("os.name").startsWith("Windows") && JavaVersion.majorVersion(JavaVersion.CURRENT) == 8);
144147
final Map<String, String> heapMaxDirectMemorySize = new HashMap<>();
145148
heapMaxDirectMemorySize.put("64M", Long.toString((64L << 20) / 2));
@@ -156,8 +159,10 @@ public void testMaxDirectMemorySizeChoice() throws InterruptedException, IOExcep
156159
}
157160

158161
public void testMaxDirectMemorySizeChoiceWhenSet() throws InterruptedException, IOException {
162+
List<String> derivedSettingList = JvmErgonomics.choose(Arrays.asList("-Xms5g", "-Xmx5g", "-XX:MaxDirectMemorySize=4g"));
159163
assertThat(
160-
JvmErgonomics.choose(Arrays.asList("-Xms1g", "-Xmx1g", "-XX:MaxDirectMemorySize=1g")),
164+
derivedSettingList,
165+
// if MaxDirectMemorySize is set, we shouldn't derive our own value for it
161166
everyItem(not(startsWith("-XX:MaxDirectMemorySize="))));
162167
}
163168

0 commit comments

Comments
 (0)