Introduce multi-release JAR

This commit introduces the ability for the core Elasticsearch JAR to be
a multi-release JAR containing code that is compiled for JDK 8 and code
that is compiled for JDK 9. At runtime, a JDK 8 JVM will ignore the JDK
9 compiled classfiles, and a JDK 9 JVM will use the JDK 9 compiled
classfiles instead of the JDK 8 compiled classfiles. With this work, we
utilize the new JDK 9 API for obtaining the PID of the running JVM,
instead of relying on a hack.

For now, we want to keep IDEs on JDK 8 so when the build is in an IDE we
ignore the JDK 9 source set (as otherwise the IDE would give compilation
errors). However, with this change, running Gradle from the command-line
now requires JAVA_HOME and JAVA_9_HOME to be set. This will require
follow-up work in our CI infrastructure and our release builds to
accommodate this change.

Relates #28051
This commit is contained in:
Jason Tedor 2018-01-16 15:10:29 -05:00 committed by GitHub
parent e5a698447b
commit 045dd4ad48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 113 additions and 14 deletions

View File

@ -158,8 +158,10 @@ class BuildPlugin implements Plugin<Project> {
project.rootProject.ext.runtimeJavaVersion = runtimeJavaVersionEnum
project.rootProject.ext.buildChecksDone = true
}
project.targetCompatibility = minimumRuntimeVersion
project.sourceCompatibility = minimumRuntimeVersion
// set java home for each project, so they dont have to find it in the root project
project.ext.compilerJavaHome = project.rootProject.ext.compilerJavaHome
project.ext.runtimeJavaHome = project.rootProject.ext.runtimeJavaHome
@ -421,12 +423,12 @@ class BuildPlugin implements Plugin<Project> {
}
project.afterEvaluate {
project.tasks.withType(JavaCompile) {
File gradleJavaHome = Jvm.current().javaHome
final JavaVersion targetCompatibilityVersion = JavaVersion.toVersion(it.targetCompatibility)
// we fork because compiling lots of different classes in a shared jvm can eventually trigger GC overhead limitations
options.fork = true
options.forkOptions.javaHome = new File(project.compilerJavaHome)
options.forkOptions.memoryMaximumSize = "1g"
if (project.targetCompatibility >= JavaVersion.VERSION_1_8) {
if (targetCompatibilityVersion == JavaVersion.VERSION_1_8) {
// compile with compact 3 profile by default
// NOTE: this is just a compile time check: does not replace testing with a compact3 JRE
if (project.compactProfile != 'full') {
@ -449,8 +451,9 @@ class BuildPlugin implements Plugin<Project> {
options.encoding = 'UTF-8'
options.incremental = true
// TODO: use native Gradle support for --release when available (cf. https://github.com/gradle/gradle/issues/2510)
options.compilerArgs << '--release' << project.targetCompatibility.majorVersion
options.compilerArgs << '--release' << targetCompatibilityVersion.majorVersion
}
}
}

View File

@ -36,6 +36,29 @@ publishing {
archivesBaseName = 'elasticsearch'
// we want to keep the JDKs in our IDEs set to JDK 8 until minimum JDK is bumped to 9 so we do not include this source set in our IDEs
if (!isEclipse && !isIdea) {
sourceSets {
java9 {
java {
srcDirs = ['src/main/java9']
}
}
}
compileJava9Java {
sourceCompatibility = 9
targetCompatibility = 9
}
jar {
into('META-INF/versions/9') {
from sourceSets.java9.output
}
manifest.attributes('Multi-Release': 'true')
}
}
dependencies {
compile "org.elasticsearch:elasticsearch-core:${version}"
@ -94,6 +117,10 @@ dependencies {
// repackaged jna with native bits linked against all elastic supported platforms
compile "org.elasticsearch:jna:${versions.jna}"
if (!isEclipse && !isIdea) {
java9Compile sourceSets.main.output
}
if (isEclipse == false || project.path == ":server-tests") {
testCompile("org.elasticsearch.test:framework:${version}") {
// tests use the locally compiled version of server

View File

@ -47,16 +47,6 @@ public class JvmInfo implements Writeable, ToXContentFragment {
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
// returns the <process id>@<host>
long pid;
String xPid = runtimeMXBean.getName();
try {
xPid = xPid.split("@")[0];
pid = Long.parseLong(xPid);
} catch (Exception e) {
pid = -1;
}
long heapInit = memoryMXBean.getHeapMemoryUsage().getInit() < 0 ? 0 : memoryMXBean.getHeapMemoryUsage().getInit();
long heapMax = memoryMXBean.getHeapMemoryUsage().getMax() < 0 ? 0 : memoryMXBean.getHeapMemoryUsage().getMax();
long nonHeapInit = memoryMXBean.getNonHeapMemoryUsage().getInit() < 0 ? 0 : memoryMXBean.getNonHeapMemoryUsage().getInit();
@ -160,7 +150,7 @@ public class JvmInfo implements Writeable, ToXContentFragment {
}
INSTANCE = new JvmInfo(pid, System.getProperty("java.version"), runtimeMXBean.getVmName(), runtimeMXBean.getVmVersion(),
INSTANCE = new JvmInfo(JvmPid.getPid(), System.getProperty("java.version"), runtimeMXBean.getVmName(), runtimeMXBean.getVmVersion(),
runtimeMXBean.getVmVendor(), runtimeMXBean.getStartTime(), configuredInitialHeapSize, configuredMaxHeapSize,
mem, inputArguments, bootClassPath, classPath, systemProperties, gcCollectors, memoryPools, onError, onOutOfMemoryError,
useCompressedOops, useG1GC, useSerialGC);

View File

@ -0,0 +1,49 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.monitor.jvm;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.elasticsearch.common.logging.Loggers;
import java.lang.management.ManagementFactory;
class JvmPid {
private static final long PID;
static long getPid() {
return PID;
}
static {
PID = initializePid();
}
private static long initializePid() {
final String name = ManagementFactory.getRuntimeMXBean().getName();
try {
return Long.parseLong(name.split("@")[0]);
} catch (final NumberFormatException e) {
Loggers.getLogger(JvmPid.class).debug(new ParameterizedMessage("failed parsing PID from [{}]", name), e);
return -1;
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.monitor.jvm;
import java.lang.ProcessHandle;
class JvmPid {
static long getPid() {
return ProcessHandle.current().pid();
}
}