diff -Nru gradle-4.4/debian/changelog gradle-4.4/debian/changelog --- gradle-4.4/debian/changelog 2018-10-01 14:12:33.000000000 +0100 +++ gradle-4.4/debian/changelog 2018-10-01 20:05:23.000000000 +0100 @@ -1,3 +1,17 @@ +gradle (4.4-3ubuntu1) cosmic; urgency=medium + + * Enable support for openjdk-11 (Closes: #909905, LP: #1795767) + - debian/patches/enable-jdk-11-support-ac15612d41b43c39c.patch: + enable support for openjdk-11. + - d/p/use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch: + Use Lookup to invoke defineClass on Java 9+. + - d/p/do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch: + Don't use ClassLoader.getDefinedPackages() on Java 9. + - d/p/use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.path: + Use Lookup instead of reflection on Java 9+. + + -- Tiago Stürmer Daitx Mon, 01 Oct 2018 19:05:23 +0000 + gradle (4.4-3) unstable; urgency=medium * Team upload. diff -Nru gradle-4.4/debian/control gradle-4.4/debian/control --- gradle-4.4/debian/control 2018-09-16 22:04:25.000000000 +0100 +++ gradle-4.4/debian/control 2018-09-29 21:25:39.000000000 +0100 @@ -1,5 +1,6 @@ Source: gradle -Maintainer: Debian Java Maintainers +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Java Maintainers Uploaders: Kai-Chung Yan Section: java Priority: optional diff -Nru gradle-4.4/debian/patches/do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch gradle-4.4/debian/patches/do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch --- gradle-4.4/debian/patches/do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch 1970-01-01 01:00:00.000000000 +0100 +++ gradle-4.4/debian/patches/do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch 2018-10-01 20:05:23.000000000 +0100 @@ -0,0 +1,149 @@ +Description: Don't use ClassLoader.getDefinedPackages() on Java 9 + Prior to this change, FilteringClassLoader invokes + ClassLoader.getSystemClassLoader().getParent().getDefinedPackages() + to get all system packages on Java 9, which is not correct. + ClassLoader.getDefinedPackages() only fetches packages defined by + the ClassLoader itself, not including its parent's. The consequence is, + on Java 9, most Java SE and JDK packages (e.g. java.lang) are not included in + FilteringClassLoader.SYSTEM_PACKAGES. + + This PR fixes this problem by using ClassLoader.getPackages() all the time. +Origin: upstream, https://github.com/gradle/gradle/commit/50eababaa25230abc73899eda768dd0646ddcdb4 +Bug: https://github.com/gradle/gradle/pull/5477 +Bug-Debian: https://bugs.debian.org/909905 +Forwarded: not-needed +Applied-Upstream: 50eababaa25230abc73899eda768dd0646ddcdb4 +Last-Update: 2018-10-01 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +From 50eababaa25230abc73899eda768dd0646ddcdb4 Mon Sep 17 00:00:00 2001 +From: Bo Zhang +Date: Wed, 23 May 2018 16:24:05 +0800 +Subject: [PATCH] Don't use ClassLoader.getDefinedPackages() on Java 9 (#5477) + +Prior to this change, FilteringClassLoader invokes +ClassLoader.getSystemClassLoader().getParent().getDefinedPackages() +to get all system packages on Java 9, which is not correct. +ClassLoader.getDefinedPackages() only fetches packages defined by +the ClassLoader itself, not including its parent's. The consequence is, +on Java 9, most Java SE and JDK packages (e.g. java.lang) are not included in +FilteringClassLoader.SYSTEM_PACKAGES. + +This PR fixes this problem by using ClassLoader.getPackages() all the time. +--- + .../classloader/ClassLoaderUtils.java | 4 ++-- + .../classloader/FilteringClassLoader.java | 22 +++++++++---------- + .../FilteringClassLoaderTest.groovy | 6 +---- + .../fixtures/executer/LogContent.java | 2 +- + ...ConsoleJvmTestLoggingFunctionalTest.groovy | 3 ++- + 5 files changed, 17 insertions(+), 20 deletions(-) + +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +index 3995ad38be55..cdd68af5f905 100644 +--- a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +@@ -39,7 +39,8 @@ + + static { + CLASS_DEFINER = JavaVersion.current().isJava9Compatible() ? new LookupClassDefiner() : new ReflectionClassDefiner(); +- GET_PACKAGES_METHOD = getMethodWithFallback(Package[].class, new Class[0], "getDefinedPackages", "getPackages"); ++ GET_PACKAGES_METHOD = method(ClassLoader.class, Package[].class, "getPackages"); ++ // Since Java 9, getPackage() is deprecated, so we use getDefinedPackage() instead + GET_PACKAGE_METHOD = getMethodWithFallback(Package.class, new Class[]{String.class}, "getDefinedPackage", "getPackage"); + } + +@@ -48,7 +49,6 @@ + try { + method = method(ClassLoader.class, clazz, firstChoice, params); + } catch (Throwable e) { +- // We must not be on Java 9 where the getDefinedPackages() method exists. Fall back to getPackages() + method = method(ClassLoader.class, clazz, fallback, params); + } + return method; +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java +index edbc6242cdea..b658a0c70ac8 100644 +--- a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/FilteringClassLoader.java +@@ -16,9 +16,6 @@ + + package org.gradle.internal.classloader; + +-import org.gradle.internal.UncheckedException; +-import org.gradle.internal.reflect.JavaMethod; +- + import java.io.IOException; + import java.net.URL; + import java.util.ArrayList; +@@ -46,14 +43,7 @@ + + static { + EXT_CLASS_LOADER = ClassLoaderUtils.getPlatformClassLoader(); +- Package[] systemPackages; +- JavaMethod method = ClassLoaderUtils.getPackagesMethod(); +- try { +- systemPackages = method.invoke(EXT_CLASS_LOADER); +- } catch (Exception e) { +- throw UncheckedException.throwAsUncheckedException(e); +- } +- for (Package p : systemPackages) { ++ for (Package p : new RetrieveSystemPackagesClassLoader(EXT_CLASS_LOADER).getPackages()) { + SYSTEM_PACKAGES.add(p.getName()); + } + try { +@@ -64,6 +54,16 @@ + } + } + ++ private static class RetrieveSystemPackagesClassLoader extends ClassLoader { ++ RetrieveSystemPackagesClassLoader(ClassLoader parent) { ++ super(parent); ++ } ++ ++ protected Package[] getPackages() { ++ return super.getPackages(); ++ } ++ } ++ + public FilteringClassLoader(ClassLoader parent, Spec spec) { + super(parent); + packageNames.addAll(spec.packageNames); +diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy +index a1d50b809f2f..54a82d44cd51 100644 +--- a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy ++++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/FilteringClassLoaderTest.groovy +@@ -23,7 +23,6 @@ import org.junit.runners.BlockJUnit4ClassRunner + import spock.lang.Issue + import spock.lang.Specification + +-import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 + import static org.junit.Assert.fail + + class FilteringClassLoaderTest extends Specification { +@@ -38,17 +37,15 @@ class FilteringClassLoaderTest extends Specification { + canLoadClass(String) + } + +- @Requires(FIX_TO_WORK_ON_JAVA9) + void passesThroughSystemPackages() { + expect: + canSeePackage('java.lang') + } + + @Issue("gradle/core-issues#115") +- @Requires(FIX_TO_WORK_ON_JAVA9) + void passesThroughSystemResources() { + expect: +- canSeeResource('com/sun/jndi/ldap/jndiprovider.properties') ++ canSeeResource('java/lang/Object.class') + } + + void filtersClassesByDefault() { +@@ -70,7 +67,6 @@ class FilteringClassLoaderTest extends Specification { + e2.message == "$Test.name not found." + } + +- @Requires(TestPrecondition.JDK8_OR_EARLIER) + void filtersPackagesByDefault() { + given: + assert classLoader.parent.getPackage('org.junit') != null diff -Nru gradle-4.4/debian/patches/enable-jdk-11-support-ac15612d41b43c39c.patch gradle-4.4/debian/patches/enable-jdk-11-support-ac15612d41b43c39c.patch --- gradle-4.4/debian/patches/enable-jdk-11-support-ac15612d41b43c39c.patch 1970-01-01 01:00:00.000000000 +0100 +++ gradle-4.4/debian/patches/enable-jdk-11-support-ac15612d41b43c39c.patch 2018-09-29 21:11:59.000000000 +0100 @@ -0,0 +1,560 @@ +Description: make JavaVersion support JDK 11 and JEP-223 + Add JavaVersion.VERSION_11 and support JEP223 +Origin: upstream, https://github.com/gradle/gradle/commit/ac15612d41b43c39c8e39d12fdd6621589b0f782 +Bug-Debian: http://bugs.debian.org/909905 +Forwarded: not-needed +Applied-Upstream: ac15612d41b43c39c8e39d12fdd6621589b0f782 +Last-Update: 2018-09-29 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +From ac15612d41b43c39c8e39d12fdd6621589b0f782 Mon Sep 17 00:00:00 2001 +From: Bo Zhang +Date: Wed, 21 Mar 2018 16:08:44 +0800 +Subject: [PATCH] Make JavaVersion support JDK 11 and JEP-223 (#4759) + +Add JavaVersion.VERSION_11 and support JEP223 +--- + .../main/java/org/gradle/api/JavaVersion.java | 123 ++++++---- + .../org/gradle/api/JavaVersionSpec.groovy | 212 ++++++++---------- + .../changes/accepted-public-api-changes.json | 20 ++ + .../cli/BuildActionsFactoryTest.groovy | 8 +- + 4 files changed, 199 insertions(+), 164 deletions(-) + +--- a/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java ++++ b/subprojects/base-services/src/main/java/org/gradle/api/JavaVersion.java +@@ -17,25 +17,26 @@ package org.gradle.api; + + import com.google.common.annotations.VisibleForTesting; + +-import java.util.regex.Matcher; +-import java.util.regex.Pattern; ++import java.util.ArrayList; ++import java.util.List; + + /** + * An enumeration of Java versions. ++ * Before 9: http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html ++ * 9+: http://openjdk.java.net/jeps/223 + */ + public enum JavaVersion { +- VERSION_1_1(false), VERSION_1_2(false), VERSION_1_3(false), VERSION_1_4(false), +- // starting from here versions are 1_ but their official name is "Java 6", "Java 7", ... +- VERSION_1_5(true), VERSION_1_6(true), VERSION_1_7(true), VERSION_1_8(true), VERSION_1_9(true), VERSION_1_10(true); ++ VERSION_1_1, VERSION_1_2, VERSION_1_3, VERSION_1_4, ++ VERSION_1_5, VERSION_1_6, VERSION_1_7, VERSION_1_8, ++ VERSION_1_9, VERSION_1_10, VERSION_11, VERSION_HIGHER; ++ // Since Java 9, version should be X instead of 1.X ++ // However, to keep backward compatibility, we change from 11 ++ private static final int FIRST_MAJOR_VERSION_ORDINAL = 10; + private static JavaVersion currentJavaVersion; +- private final boolean hasMajorVersion; + private final String versionName; +- private final String majorVersion; + +- JavaVersion(boolean hasMajorVersion) { +- this.hasMajorVersion = hasMajorVersion; +- this.versionName = name().substring("VERSION_".length()).replace('_', '.'); +- this.majorVersion = name().substring(10); ++ JavaVersion() { ++ this.versionName = ordinal() >= FIRST_MAJOR_VERSION_ORDINAL ? getMajorVersion() : "1." + getMajorVersion(); + } + + /** +@@ -54,22 +55,18 @@ public enum JavaVersion { + } + + String name = value.toString(); +- Matcher matcher = Pattern.compile("(\\d{1,2})(\\D.+)?").matcher(name); +- if (matcher.matches()) { +- int index = Integer.parseInt(matcher.group(1)) - 1; +- if (index > 0 && index < values().length && values()[index].hasMajorVersion) { +- return values()[index]; +- } +- } + +- matcher = Pattern.compile("1\\.(\\d{1,2})(\\D.+)?").matcher(name); +- if (matcher.matches()) { +- int versionIdx = Integer.parseInt(matcher.group(1)) - 1; +- if (versionIdx >= 0 && versionIdx < values().length) { +- return values()[versionIdx]; +- } ++ int firstNonVersionCharIndex = findFirstNonVersionCharIndex(name); ++ ++ String[] versionStrings = name.substring(0, firstNonVersionCharIndex).split("\\."); ++ List versions = convertToNumber(name, versionStrings); ++ ++ if (isLegacyVersion(versions)) { ++ assertTrue(name, versions.get(1) > 0); ++ return getVersionForMajor(versions.get(1)); ++ } else { ++ return getVersionForMajor(versions.get(0)); + } +- throw new IllegalArgumentException(String.format("Could not determine java version from '%s'.", name)); + } + + /** +@@ -90,11 +87,7 @@ public enum JavaVersion { + } + + public static JavaVersion forClassVersion(int classVersion) { +- int index = classVersion - 45; //class file versions: 1.1 == 45, 1.2 == 46... +- if (index >= 0 && index < values().length) { +- return values()[index]; +- } +- throw new IllegalArgumentException(String.format("Could not determine java version from '%d'.", classVersion)); ++ return getVersionForMajor(classVersion - 44); //class file versions: 1.1 == 45, 1.2 == 46... + } + + public static JavaVersion forClass(byte[] classData) { +@@ -116,18 +109,22 @@ public enum JavaVersion { + return this == VERSION_1_7; + } + +- private boolean isJava8() { ++ public boolean isJava8() { + return this == VERSION_1_8; + } + +- private boolean isJava9() { ++ public boolean isJava9() { + return this == VERSION_1_9; + } + +- private boolean isJava10() { ++ public boolean isJava10() { + return this == VERSION_1_10; + } + ++ public boolean isJava11() { ++ return this == VERSION_11; ++ } ++ + public boolean isJava5Compatible() { + return this.compareTo(VERSION_1_5) >= 0; + } +@@ -148,21 +145,69 @@ public enum JavaVersion { + return this.compareTo(VERSION_1_9) >= 0; + } + +- @Incubating + public boolean isJava10Compatible() { + return this.compareTo(VERSION_1_10) >= 0; + } + +- @Override +- public String toString() { +- return getName(); ++ public boolean isJava11Compatible() { ++ return this.compareTo(VERSION_11) >= 0; + } + +- private String getName() { ++ @Override ++ public String toString() { + return versionName; + } + + public String getMajorVersion() { +- return majorVersion; ++ return String.valueOf(ordinal() + 1); ++ } ++ ++ private static JavaVersion getVersionForMajor(int major) { ++ return major >= values().length ? JavaVersion.VERSION_HIGHER : values()[major - 1]; ++ } ++ ++ private static void assertTrue(String value, boolean condition) { ++ if (!condition) { ++ throw new IllegalArgumentException("Could not determine java version from '" + value + "'."); ++ } ++ } ++ ++ private static boolean isLegacyVersion(List versions) { ++ return 1 == versions.get(0) && versions.size() > 1; ++ } ++ ++ private static List convertToNumber(String value, String[] versionStrs) { ++ List result = new ArrayList(); ++ for (String s : versionStrs) { ++ assertTrue(value, !isNumberStartingWithZero(s)); ++ try { ++ result.add(Integer.parseInt(s)); ++ } catch (NumberFormatException e) { ++ assertTrue(value, false); ++ } ++ } ++ assertTrue(value, !result.isEmpty() && result.get(0) > 0); ++ return result; ++ } ++ ++ private static boolean isNumberStartingWithZero(String number) { ++ return number.length() > 1 && number.startsWith("0"); ++ } ++ ++ private static int findFirstNonVersionCharIndex(String s) { ++ assertTrue(s, s.length() != 0); ++ ++ for (int i = 0; i < s.length(); ++i) { ++ if (!isDigitOrPeriod(s.charAt(i))) { ++ assertTrue(s, i != 0); ++ return i; ++ } ++ } ++ ++ return s.length(); ++ } ++ ++ private static boolean isDigitOrPeriod(char c) { ++ return (c >= '0' && c <= '9') || c == '.'; + } + } +--- a/subprojects/base-services/src/test/groovy/org/gradle/api/JavaVersionSpec.groovy ++++ b/subprojects/base-services/src/test/groovy/org/gradle/api/JavaVersionSpec.groovy +@@ -13,16 +13,20 @@ + * See the License for the specific language governing permissions and + * limitations under the License. + */ +-package org.gradle.api; ++package org.gradle.api + + + import org.gradle.util.SetSystemProperties + import org.junit.Rule + import spock.lang.Specification ++import spock.lang.Unroll + +-public class JavaVersionSpec extends Specification { ++class JavaVersionSpec extends Specification { ++ private static final BigInteger TOO_BIG = (BigInteger.valueOf(Integer.MAX_VALUE)).add(BigInteger.ONE) ++ private static final String TOO_BIG_STR = TOO_BIG.toString() + +- @Rule SetSystemProperties sysProp = new SetSystemProperties() ++ @Rule ++ SetSystemProperties sysProp = new SetSystemProperties() + + def setup() { + JavaVersion.resetCurrent() +@@ -42,6 +46,8 @@ public class JavaVersionSpec extends Spe + JavaVersion.VERSION_1_8.toString() == "1.8" + JavaVersion.VERSION_1_9.toString() == "1.9" + JavaVersion.VERSION_1_10.toString() == "1.10" ++ JavaVersion.VERSION_11.toString() == "11" ++ JavaVersion.VERSION_HIGHER.toString() == "12" + } + + def convertsStringToVersion() { +@@ -71,6 +77,10 @@ public class JavaVersionSpec extends Spe + JavaVersion.toVersion("10.1.2") == JavaVersion.VERSION_1_10 + JavaVersion.toVersion("10-ea") == JavaVersion.VERSION_1_10 + JavaVersion.toVersion("10-internal") == JavaVersion.VERSION_1_10 ++ ++ JavaVersion.toVersion("11-ea") == JavaVersion.VERSION_11 ++ JavaVersion.toVersion("12-ea") == JavaVersion.VERSION_HIGHER ++ JavaVersion.toVersion("999-ea") == JavaVersion.VERSION_HIGHER + } + + def convertClassVersionToJavaVersion() { +@@ -85,27 +95,26 @@ public class JavaVersionSpec extends Spe + JavaVersion.forClassVersion(52) == JavaVersion.VERSION_1_8 + JavaVersion.forClassVersion(53) == JavaVersion.VERSION_1_9 + JavaVersion.forClassVersion(54) == JavaVersion.VERSION_1_10 ++ JavaVersion.forClassVersion(55) == JavaVersion.VERSION_11 ++ JavaVersion.forClassVersion(999) == JavaVersion.VERSION_HIGHER + } + + def failsToConvertStringToVersionForUnknownVersion() { + expect: +- conversionFails("1"); +- conversionFails("2"); +- +- conversionFails("17"); +- +- conversionFails("a"); +- conversionFails("java-9"); +- conversionFails(""); +- conversionFails(" "); +- +- conversionFails("0.1"); +- conversionFails("1.54"); +- conversionFails("2.0"); +- conversionFails("1_4"); +- +- conversionFails("9-"); +- conversionFails("11-ea"); ++ conversionFails("a") ++ conversionFails("java-9") ++ conversionFails("") ++ conversionFails(" ") ++ ++ conversionFails("0.1") ++ conversionFails("0.1") ++ ++ conversionFails('foo') ++ conversionFails('0') ++ conversionFails('1.00') ++ conversionFails('00') ++ conversionFails('09') ++ conversionFails(TOO_BIG_STR) + } + + def convertsVersionToVersion() { +@@ -127,16 +136,6 @@ public class JavaVersionSpec extends Spe + JavaVersion.toVersion(10) == JavaVersion.VERSION_1_10 + } + +- def failsToConvertNumberToVersionForUnknownVersion() { +- expect: +- conversionFails(1); +- conversionFails(2); +- conversionFails(17); +- conversionFails(1.21); +- conversionFails(2.0); +- conversionFails(4.2); +- } +- + def currentReturnsJvmVersion() { + expect: + JavaVersion.current() == JavaVersion.toVersion(System.getProperty("java.version")) +@@ -149,118 +148,89 @@ public class JavaVersionSpec extends Spe + + private void conversionFails(Object value) { + try { +- JavaVersion.toVersion(value); +- org.junit.Assert.fail(); ++ JavaVersion.toVersion(value) ++ org.junit.Assert.fail() + } catch (IllegalArgumentException e) { + assert e.getMessage() == "Could not determine java version from '" + value + "'." + } + } + +- def "uses system property to determine if compatible with Java 5"() { +- System.properties['java.version'] = '1.5' +- +- expect: +- JavaVersion.current().java5 +- !JavaVersion.current().java6 +- !JavaVersion.current().java7 +- !JavaVersion.current().java8 +- +- and: +- JavaVersion.current().java5Compatible +- !JavaVersion.current().java6Compatible +- !JavaVersion.current().java7Compatible +- !JavaVersion.current().java8Compatible +- } +- +- def "uses system property to determine if compatible with Java 6"() { +- System.properties['java.version'] = '1.6' +- +- expect: +- !JavaVersion.current().java5 +- JavaVersion.current().java6 +- !JavaVersion.current().java7 +- !JavaVersion.current().java8 +- +- and: +- JavaVersion.current().java5Compatible +- JavaVersion.current().java6Compatible +- !JavaVersion.current().java7Compatible +- !JavaVersion.current().java8Compatible +- } +- +- def "uses system property to determine if compatible with Java 7"() { +- System.properties['java.version'] = '1.7' +- +- expect: +- !JavaVersion.current().java5 +- !JavaVersion.current().java6 +- JavaVersion.current().java7 +- !JavaVersion.current().java8 +- +- and: +- JavaVersion.current().java5Compatible +- JavaVersion.current().java6Compatible +- JavaVersion.current().java7Compatible +- !JavaVersion.current().java8Compatible +- } +- +- def "uses system property to determine if compatible with Java 8"() { +- System.properties['java.version'] = '1.8' +- +- expect: +- !JavaVersion.current().java5 +- !JavaVersion.current().java6 +- !JavaVersion.current().java7 +- JavaVersion.current().java8 +- +- and: +- JavaVersion.current().java5Compatible +- JavaVersion.current().java6Compatible +- JavaVersion.current().java7Compatible +- JavaVersion.current().java8Compatible +- } +- +- def "uses system property to determine if compatible with Java 9"() { +- System.properties['java.version'] = javaVersion +- +- expect: +- !JavaVersion.current().java5 +- !JavaVersion.current().java6 +- !JavaVersion.current().java7 +- !JavaVersion.current().java8 +- JavaVersion.current().java9 +- +- and: +- JavaVersion.current().java5Compatible +- JavaVersion.current().java6Compatible +- JavaVersion.current().java7Compatible +- JavaVersion.current().java8Compatible +- JavaVersion.current().java9Compatible +- +- where: +- javaVersion << ['1.9', '9-ea'] +- } +- +- def "uses system property to determine if compatible with Java 10"() { +- System.properties['java.version'] = javaVersion +- +- expect: +- !JavaVersion.current().java5 +- !JavaVersion.current().java6 +- !JavaVersion.current().java7 +- !JavaVersion.current().java8 +- !JavaVersion.current().java9 +- JavaVersion.current().java10 +- +- and: +- JavaVersion.current().java5Compatible +- JavaVersion.current().java6Compatible +- JavaVersion.current().java7Compatible +- JavaVersion.current().java8Compatible +- JavaVersion.current().java9Compatible +- JavaVersion.current().java10Compatible ++ @Unroll ++ def "uses system property to determine if compatible with Java #versionString"() { ++ System.properties['java.version'] = versionString ++ ++ expect: ++ JavaVersion.current() == current ++ JavaVersion.current().java6 == isJava6 ++ JavaVersion.current().java7 == isJava7 ++ JavaVersion.current().java8 == isJava8 ++ JavaVersion.current().java9 == isJava9 ++ JavaVersion.current().java10 == isJava10 ++ JavaVersion.current().java11 == isJava11 ++ ++ and: ++ JavaVersion.current().java6Compatible == isJava6Compatible ++ JavaVersion.current().java7Compatible == isJava7Compatible ++ JavaVersion.current().java8Compatible == isJava8Compatible ++ JavaVersion.current().java9Compatible == isJava9Compatible ++ JavaVersion.current().java10Compatible == isJava10Compatible ++ JavaVersion.current().java11Compatible == isJava11Compatible + + where: +- javaVersion << ['1.10', '10-ea'] ++ versionString | current | isJava6 | isJava7 | isJava8 | isJava9 | isJava10 | isJava11 | isJava6Compatible | isJava7Compatible | isJava8Compatible | isJava9Compatible | isJava10Compatible | isJava11Compatible ++ '1.5' | JavaVersion.VERSION_1_5 | false | false | false | false | false | false | false | false | false | false | false | false ++ '1.6' | JavaVersion.VERSION_1_6 | true | false | false | false | false | false | true | false | false | false | false | false ++ '1.7' | JavaVersion.VERSION_1_7 | false | true | false | false | false | false | true | true | false | false | false | false ++ '1.8' | JavaVersion.VERSION_1_8 | false | false | true | false | false | false | true | true | true | false | false | false ++ '1.9' | JavaVersion.VERSION_1_9 | false | false | false | true | false | false | true | true | true | true | false | false ++ '9-ea' | JavaVersion.VERSION_1_9 | false | false | false | true | false | false | true | true | true | true | false | false ++ '1.10' | JavaVersion.VERSION_1_10 | false | false | false | false | true | false | true | true | true | true | true | false ++ '10-ea' | JavaVersion.VERSION_1_10 | false | false | false | false | true | false | true | true | true | true | true | false ++ '1.11' | JavaVersion.VERSION_11 | false | false | false | false | false | true | true | true | true | true | true | true ++ '11-ea' | JavaVersion.VERSION_11 | false | false | false | false | false | true | true | true | true | true | true | true ++ '12' | JavaVersion.VERSION_HIGHER | false | false | false | false | false | false | true | true | true | true | true | true ++ '999' | JavaVersion.VERSION_HIGHER | false | false | false | false | false | false | true | true | true | true | true | true ++ } ++ ++ /* Following test cases are from http://hg.openjdk.java.net/jdk/jdk/file/af37d9997bd6/test/jdk/java/lang/Runtime/Version/Basic.java */ ++ ++ def 'can recognize multiple version number'() { ++ expect: ++ JavaVersion.toVersion('9') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9.1') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9.0.1') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9.0.0.1') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9.0.0.0.1') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('404.1.2') == JavaVersion.VERSION_HIGHER ++ JavaVersion.toVersion('9.1.2.3') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('1000.0.0.0.0.0.99999999') == JavaVersion.VERSION_HIGHER ++ } ++ ++ def 'can recognize version with $pre'() { ++ expect: ++ JavaVersion.toVersion('9-ea') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9-internal') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9-0') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9.2.7-8') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('2.3.4.5-1a') == JavaVersion.VERSION_1_2 ++ } ++ ++ def 'can recognize $build'() { ++ expect: ++ JavaVersion.toVersion('9+0') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('3.14+9999900') == JavaVersion.VERSION_1_3 ++ JavaVersion.toVersion('9-pre+105') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('6.0.42-8beta+4') == JavaVersion.VERSION_1_6 ++ } ++ ++ def 'can recognize version with $opt'() { ++ expect: ++ JavaVersion.toVersion('9+-foo') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('9-pre-opt') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion('42+---bar') == JavaVersion.VERSION_HIGHER ++ JavaVersion.toVersion('2.91+-8061493-') == JavaVersion.VERSION_1_2 ++ JavaVersion.toVersion('24+-foo.bar') == JavaVersion.VERSION_HIGHER ++ JavaVersion.toVersion('9-ribbit+17-...') == JavaVersion.VERSION_1_9 ++ JavaVersion.toVersion("7+1-$TOO_BIG_STR") == JavaVersion.VERSION_1_7 + } + } +--- a/subprojects/distributions/src/changes/accepted-public-api-changes.json ++++ b/subprojects/distributions/src/changes/accepted-public-api-changes.json +@@ -170,6 +170,26 @@ + "type": "org.gradle.api.publish.maven.plugins.MavenPublishPlugin", + "member": "Constructor org.gradle.api.publish.maven.plugins.MavenPublishPlugin(org.gradle.internal.reflect.Instantiator,org.gradle.api.internal.artifacts.configurations.DependencyMetaDataProvider,org.gradle.api.internal.file.FileResolver,org.gradle.api.publish.internal.ProjectDependencyPublicationResolver,org.gradle.api.internal.file.FileCollectionFactory,org.gradle.api.internal.ExperimentalFeatures)", + "acceptation": "Change to constructor of incubating plugin" ++ }, ++ { ++ "type": "org.gradle.api.JavaVersion", ++ "member": "Field VERSION_11", ++ "acceptation": "Support JDK 11" ++ }, ++ { ++ "type": "org.gradle.api.JavaVersion", ++ "member": "Field VERSION_HIGHER", ++ "acceptation": "Support JDK 11" ++ }, ++ { ++ "type": "org.gradle.api.JavaVersion", ++ "member": "Method org.gradle.api.JavaVersion.isJava11()", ++ "acceptation": "Support JDK 11" ++ }, ++ { ++ "type": "org.gradle.api.JavaVersion", ++ "member": "Method org.gradle.api.JavaVersion.isJava11Compatible()", ++ "acceptation": "Support JDK 11" + } + ] + } +--- a/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy ++++ b/subprojects/launcher/src/test/groovy/org/gradle/launcher/cli/BuildActionsFactoryTest.groovy +@@ -57,10 +57,10 @@ class BuildActionsFactoryTest extends Sp + PropertiesToStartParameterConverter propertiesToStartParameterConverter = Stub() + JvmVersionDetector jvmVersionDetector = Stub() + ParametersConverter parametersConverter = new ParametersConverter( +- Stub(LayoutCommandLineConverter), Stub(SystemPropertiesCommandLineConverter), +- Stub(LayoutToPropertiesConverter), propertiesToStartParameterConverter, +- new DefaultCommandLineConverter(), new DaemonCommandLineConverter(), +- propertiesToDaemonParametersConverter) ++ Stub(LayoutCommandLineConverter), Stub(SystemPropertiesCommandLineConverter), ++ Stub(LayoutToPropertiesConverter), propertiesToStartParameterConverter, ++ new DefaultCommandLineConverter(), new DaemonCommandLineConverter(), ++ propertiesToDaemonParametersConverter) + + BuildActionsFactory factory = new BuildActionsFactory(loggingServices, parametersConverter, jvmVersionDetector) + diff -Nru gradle-4.4/debian/patches/series gradle-4.4/debian/patches/series --- gradle-4.4/debian/patches/series 2018-10-01 14:10:47.000000000 +0100 +++ gradle-4.4/debian/patches/series 2018-09-29 21:25:43.000000000 +0100 @@ -24,3 +24,7 @@ gradle-4-compatibility.patch disable-google-apis.patch disable-internal-android-performance-testing.patch +enable-jdk-11-support-ac15612d41b43c39c.patch +use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch +do-not-use-classLoader-getdefinedpackages-on-java-9-50eababaa25230ab.patch +use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.patch diff -Nru gradle-4.4/debian/patches/use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.patch gradle-4.4/debian/patches/use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.patch --- gradle-4.4/debian/patches/use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.patch 1970-01-01 01:00:00.000000000 +0100 +++ gradle-4.4/debian/patches/use-lookup-instead-of-reflection-on-java-9-3db6e25698705317.patch 2018-10-01 20:05:23.000000000 +0100 @@ -0,0 +1,417 @@ +Description: Use Lookup instead of reflection on Java 9+ + On Java 9+, `MethodHandles.Lookup` is used to invoke protected methods + `ClassLoader.defineClass` and `ClassLoader.getDefinedPackage`. + + This patch has been modified to remove the Kotlin classes, create the + new files under subprojects/base-services instead of + subprojects/base-services-java9, and remove the test files. +Origin: upstream, https://github.com/gradle/gradle/commit/3db6e256987053171178aa96a0ef46caedc8d1a4 +Bug: https://github.com/gradle/gradle/pull/5749 +Bug-Debian: https://bugs.debian.org/909905 +Forwarded: not-needed +Applied-Upstream: 3db6e256987053171178aa96a0ef46caedc8d1a4 +Last-Update: 2018-10-01 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +From 3db6e256987053171178aa96a0ef46caedc8d1a4 Mon Sep 17 00:00:00 2001 +From: Bo Zhang +Date: Thu, 28 Jun 2018 07:48:43 +0800 +Subject: [PATCH] Use Lookup instead of reflection on Java 9+ (#5749) + +In `4.8` we have two `illegal-access` warning on Java 9+. This PR uses Java 9 API to eliminate these warning. However, the consequence is, we need Java 9 compiler to compile the specific subproject `base-servces-java9`. + +On Java 9+, `MethodHandles.Lookup` is used to invoke protected methods `ClassLoader.defineClass` and `ClassLoader.getDefinedPackage`. +--- + .../java/AvailableJavaInstallations.kt | 12 ++- + .../test/integrationtests/DistributionTest.kt | 1 + + .../UnitTestAndCompilePlugin.kt | 31 ++++---- + settings.gradle.kts | 1 + + .../base-services-java9.gradle.kts | 36 +++++++++ + .../internal/classloader/ClassDefiner.java | 21 +++++ + .../ClassLoaderPackagesFetcher.java | 23 ++++++ + .../classloader/LookupClassDefiner.java | 47 +++++++++++ + .../classloader/LookupPackagesFetcher.java | 57 +++++++++++++ + .../base-services/base-services.gradle.kts | 1 + + .../classloader/ClassLoaderUtils.java | 79 ++++--------------- + .../classloader/MultiParentClassLoader.java | 8 +- + .../child/WorkerProcessClassPathProvider.java | 8 ++ + .../gradle/DistributionIntegrationSpec.groovy | 4 +- + .../SrcDistributionIntegrationSpec.groovy | 1 + + .../GradleBuildPerformanceTest.groovy | 11 ++- + .../GradleInceptionPerformanceTest.groovy | 1 + + 17 files changed, 255 insertions(+), 87 deletions(-) + create mode 100644 subprojects/base-services-java9/base-services-java9.gradle.kts + create mode 100644 subprojects/base-services-java9/src/main/java/org/gradle/internal/classloader/ClassDefiner.java + create mode 100644 subprojects/base-services-java9/src/main/java/org/gradle/internal/classloader/ClassLoaderPackagesFetcher.java + create mode 100644 subprojects/base-services-java9/src/main/java/org/gradle/internal/classloader/LookupClassDefiner.java + create mode 100644 subprojects/base-services-java9/src/main/java/org/gradle/internal/classloader/LookupPackagesFetcher.java + +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassDefiner.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassDefiner.java +new file mode 100644 +index 000000000000..0db35ece29f8 +--- /dev/null ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassDefiner.java +@@ -0,0 +1,21 @@ ++/* ++ * Copyright 2018 the original author or authors. ++ * ++ * Licensed 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.gradle.internal.classloader; ++ ++public interface ClassDefiner { ++ Class defineClass(ClassLoader classLoader, String className, byte[] classBytes); ++} +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderPackagesFetcher.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderPackagesFetcher.java +new file mode 100644 +index 000000000000..abfb066ad512 +--- /dev/null ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderPackagesFetcher.java +@@ -0,0 +1,23 @@ ++/* ++ * Copyright 2018 the original author or authors. ++ * ++ * Licensed 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.gradle.internal.classloader; ++ ++public interface ClassLoaderPackagesFetcher { ++ Package[] getPackages(ClassLoader classLoader); ++ ++ Package getPackage(ClassLoader classLoader, String name); ++} +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupClassDefiner.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupClassDefiner.java +new file mode 100644 +index 000000000000..f3a762c254fc +--- /dev/null ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupClassDefiner.java +@@ -0,0 +1,47 @@ ++/* ++ * Copyright 2018 the original author or authors. ++ * ++ * Licensed 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.gradle.internal.classloader; ++ ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.invoke.MethodType; ++ ++public class LookupClassDefiner implements ClassDefiner { ++ private final MethodHandle defineClassMethodHandle; ++ ++ LookupClassDefiner() { ++ try { ++ MethodHandles.Lookup baseLookup = MethodHandles.lookup(); ++ MethodType defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class}); ++ MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup); ++ defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType); ++ } catch (Throwable e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ @Override ++ @SuppressWarnings("unchecked") ++ public Class defineClass(ClassLoader classLoader, String className, byte[] classBytes) { ++ try { ++ return (Class) defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length); ++ } catch (Throwable e) { ++ throw new RuntimeException(e); ++ } ++ } ++} ++ +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupPackagesFetcher.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupPackagesFetcher.java +new file mode 100644 +index 000000000000..c93ea630c09c +--- /dev/null ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/LookupPackagesFetcher.java +@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2018 the original author or authors. ++ * ++ * Licensed 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.gradle.internal.classloader; ++ ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.invoke.MethodType; ++ ++public class LookupPackagesFetcher implements ClassLoaderPackagesFetcher { ++ private final MethodHandle getPackagesMethodHandle; ++ private final MethodHandle getDefinedPackageMethodHandle; ++ ++ LookupPackagesFetcher() { ++ try { ++ MethodHandles.Lookup baseLookup = MethodHandles.lookup(); ++ MethodType getPackagesMethodType = MethodType.methodType(Package[].class, new Class[]{}); ++ MethodType getDefinedPackageMethodType = MethodType.methodType(Package.class, new Class[]{String.class}); ++ MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup); ++ getPackagesMethodHandle = lookup.findVirtual(ClassLoader.class, "getPackages", getPackagesMethodType); ++ getDefinedPackageMethodHandle = lookup.findVirtual(ClassLoader.class, "getDefinedPackage", getDefinedPackageMethodType); ++ } catch (Throwable e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ @Override ++ public Package[] getPackages(ClassLoader classLoader) { ++ try { ++ return (Package[]) getPackagesMethodHandle.bindTo(classLoader).invokeWithArguments(); ++ } catch (Throwable e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ @Override ++ public Package getPackage(ClassLoader classLoader, String name) { ++ try { ++ return (Package) getDefinedPackageMethodHandle.bindTo(classLoader).invokeWithArguments(name); ++ } catch (Throwable e) { ++ throw new RuntimeException(e); ++ } ++ } ++} +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +index cdd68af5f905..a224cebae15f 100644 +--- a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +@@ -23,35 +23,19 @@ + + import javax.annotation.Nullable; + import java.io.IOException; +-import java.lang.invoke.MethodHandle; +-import java.lang.invoke.MethodHandles; +-import java.lang.invoke.MethodType; + import java.net.URL; + import java.net.URLConnection; + + import static org.gradle.internal.reflect.JavaReflectionUtil.method; +-import static org.gradle.internal.reflect.JavaReflectionUtil.staticMethod; + + public abstract class ClassLoaderUtils { + private static final ClassDefiner CLASS_DEFINER; +- private static final JavaMethod GET_PACKAGES_METHOD; +- private static final JavaMethod GET_PACKAGE_METHOD; + +- static { +- CLASS_DEFINER = JavaVersion.current().isJava9Compatible() ? new LookupClassDefiner() : new ReflectionClassDefiner(); +- GET_PACKAGES_METHOD = method(ClassLoader.class, Package[].class, "getPackages"); +- // Since Java 9, getPackage() is deprecated, so we use getDefinedPackage() instead +- GET_PACKAGE_METHOD = getMethodWithFallback(Package.class, new Class[]{String.class}, "getDefinedPackage", "getPackage"); +- } ++ private static final ClassLoaderPackagesFetcher CLASS_LOADER_PACKAGES_FETCHER; + +- private static JavaMethod getMethodWithFallback(Class clazz, Class[] params, String firstChoice, String fallback) { +- JavaMethod method; +- try { +- method = method(ClassLoader.class, clazz, firstChoice, params); +- } catch (Throwable e) { +- method = method(ClassLoader.class, clazz, fallback, params); +- } +- return method; ++ static { ++ CLASS_DEFINER = JavaVersion.current().isJava9Compatible()? new LookupClassDefiner(): new ReflectionClassDefiner(); ++ CLASS_LOADER_PACKAGES_FETCHER = JavaVersion.current().isJava9Compatible()? new LookupPackagesFetcher(): new ReflectionPackagesFetcher(); + } + + /** +@@ -80,22 +64,18 @@ public static void disableUrlConnectionCaching() { + } + } + +- public static JavaMethod getPackagesMethod() { +- return GET_PACKAGES_METHOD; ++ static Package[] getPackages(ClassLoader classLoader) { ++ return CLASS_LOADER_PACKAGES_FETCHER.getPackages(classLoader); + } + +- public static JavaMethod getPackageMethod() { +- return GET_PACKAGE_METHOD; ++ static Package getPackage(ClassLoader classLoader, String name) { ++ return CLASS_LOADER_PACKAGES_FETCHER.getPackage(classLoader, name); + } + + public static Class define(ClassLoader targetClassLoader, String className, byte[] clazzBytes) { + return CLASS_DEFINER.defineClass(targetClassLoader, className, clazzBytes); + } + +- private interface ClassDefiner { +- Class defineClass(ClassLoader classLoader, String className, byte[] classBytes); +- } +- + private static class ReflectionClassDefiner implements ClassDefiner { + private final JavaMethod defineClassMethod; + +@@ -109,43 +89,18 @@ private ReflectionClassDefiner() { + } + } + +- private static class LookupClassDefiner implements ClassDefiner { +- private final Class methodHandlesLookupClass; +- private final JavaMethod methodHandlesLookup; +- private final JavaMethod methodHandlesPrivateLookupIn; +- private final JavaMethod lookupFindVirtual; +- private final MethodType defineClassMethodType; +- +- private LookupClassDefiner() { +- try { +- methodHandlesLookupClass = Class.forName("java.lang.invoke.MethodHandles$Lookup"); +- } catch (ClassNotFoundException e) { +- throw new RuntimeException(e); +- } +- methodHandlesLookup = staticMethod(MethodHandles.class, methodHandlesLookupClass, "lookup"); +- methodHandlesPrivateLookupIn = staticMethod(MethodHandles.class, methodHandlesLookupClass, "privateLookupIn", Class.class, methodHandlesLookupClass); +- lookupFindVirtual = method(methodHandlesLookupClass, MethodHandle.class, "findVirtual", Class.class, String.class, MethodType.class); +- defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class}); +- } ++ private static class ReflectionPackagesFetcher implements ClassLoaderPackagesFetcher { ++ private static final JavaMethod GET_PACKAGES_METHOD = method(ClassLoader.class, Package[].class, "getPackages"); ++ private static final JavaMethod GET_PACKAGE_METHOD = method(ClassLoader.class, Package.class, "getPackage", String.class); + +- /* +- This method is equivalent to the following code but use reflection to compile on Java 7: ++ @Override ++ public Package[] getPackages(ClassLoader classLoader) { ++ return GET_PACKAGES_METHOD.invoke(classLoader); ++ } + +- MethodHandles.Lookup baseLookup = MethodHandles.lookup(); +- MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup); +- MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType); +- handle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length)); +- */ + @Override +- public Class defineClass(ClassLoader classLoader, String className, byte[] classBytes) { +- Object baseLookup = methodHandlesLookup.invoke(null); +- Object lookup = methodHandlesPrivateLookupIn.invoke(null, ClassLoader.class, baseLookup); +- MethodHandle defineClassMethodHandle = (MethodHandle) lookupFindVirtual.invoke(lookup, ClassLoader.class, "defineClass", defineClassMethodType); +- try { +- return Cast.uncheckedCast(defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length)); +- } catch (Throwable throwable) { +- throw new RuntimeException(throwable); +- } ++ public Package getPackage(ClassLoader classLoader, String name) { ++ return GET_PACKAGE_METHOD.invoke(classLoader, name); + } + } + } +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java +index 9eefa4f29565..e16e5b8737d6 100644 +--- a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/MultiParentClassLoader.java +@@ -16,7 +16,6 @@ + package org.gradle.internal.classloader; + + import com.google.common.collect.ImmutableList; +-import org.gradle.internal.reflect.JavaMethod; + + import java.io.IOException; + import java.net.URL; +@@ -37,9 +36,6 @@ + */ + public class MultiParentClassLoader extends ClassLoader implements ClassLoaderHierarchy { + +- private static final JavaMethod GET_PACKAGES_METHOD = ClassLoaderUtils.getPackagesMethod(); +- private static final JavaMethod GET_PACKAGE_METHOD = ClassLoaderUtils.getPackageMethod(); +- + private final List parents; + + static { +@@ -90,7 +86,7 @@ public void visit(ClassLoaderVisitor visitor) { + @Override + protected Package getPackage(String name) { + for (ClassLoader parent : parents) { +- Package p = GET_PACKAGE_METHOD.invoke(parent, name); ++ Package p = ClassLoaderUtils.getPackage(parent, name); + if (p != null) { + return p; + } +@@ -102,7 +98,7 @@ protected Package getPackage(String name) { + protected Package[] getPackages() { + Set packages = new LinkedHashSet(); + for (ClassLoader parent : parents) { +- Package[] parentPackages = GET_PACKAGES_METHOD.invoke(parent); ++ Package[] parentPackages = ClassLoaderUtils.getPackages(parent); + packages.addAll(Arrays.asList(parentPackages)); + } + return packages.toArray(new Package[0]); +diff --git a/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java b/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java +index e38b81ca2443..9e238a6b2e25 100644 +--- a/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java ++++ b/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java +@@ -25,12 +25,16 @@ + import org.gradle.cache.PersistentCache; + import org.gradle.internal.Factory; + import org.gradle.internal.UncheckedException; ++import org.gradle.internal.classloader.ClassDefiner; + import org.gradle.internal.classloader.ClassLoaderHierarchy; ++import org.gradle.internal.classloader.ClassLoaderPackagesFetcher; + import org.gradle.internal.classloader.ClassLoaderSpec; + import org.gradle.internal.classloader.ClassLoaderUtils; + import org.gradle.internal.classloader.ClassLoaderVisitor; + import org.gradle.internal.classloader.FilteringClassLoader; ++import org.gradle.internal.classloader.LookupPackagesFetcher; + import org.gradle.internal.classloader.SystemClassLoaderSpec; ++import org.gradle.internal.classloader.LookupClassDefiner; + import org.gradle.internal.classpath.ClassPath; + import org.gradle.internal.classpath.DefaultClassPath; + import org.gradle.internal.reflect.JavaMethod; +@@ -139,6 +143,10 @@ public void execute(PersistentCache cache) { + BootstrapSecurityManager.class, + EncodedStream.EncodedInput.class, + ClassLoaderUtils.class, ++ ClassLoaderPackagesFetcher.class, ++ ClassDefiner.class, ++ LookupClassDefiner.class, ++ LookupPackagesFetcher.class, + FilteringClassLoader.class, + ClassLoaderHierarchy.class, + ClassLoaderVisitor.class, diff -Nru gradle-4.4/debian/patches/use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch gradle-4.4/debian/patches/use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch --- gradle-4.4/debian/patches/use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch 1970-01-01 01:00:00.000000000 +0100 +++ gradle-4.4/debian/patches/use-lookup-to-invoke-defineclass-java-9-028548460bd929fd.patch 2018-09-29 21:25:43.000000000 +0100 @@ -0,0 +1,317 @@ +Description: Use Lookup to invoke defineClass on Java 9+ + The last step of ASM bytecode generation is injecting byte[] into a + classloader to let it load the class. Before Java 9, we were using + reflection to invoke protected ClassLoader.defineClass. After Java 9, + the reflection is forbidden without implicit --add-on so we switch to + Unsafe. Unfortunately in Java 11, Unsafe is removed (#4860 ). This PR + selects class injection method according to Java runtime version: + - Use reflection to invoke ClassLoader.defineClass on Java 8 and + previous. + - Use MethodHandles.Looup to invoke ClassLoader.defineClass on Java + 9+. + It's verified on JDK 11 early preview version. +Origin: upstream, https://github.com/gradle/gradle/commit/028548460bd929fd034a552704798ad7f689493a +Bug: https://github.com/gradle/gradle/pull/4976 +Bug-Debian: https://bugs.debian.org/909905 +Forwarded: not-needed +Applied-Upstream: 028548460bd929fd034a552704798ad7f689493a +Last-Update: 2018-09-29 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ + +From 028548460bd929fd034a552704798ad7f689493a Mon Sep 17 00:00:00 2001 +From: Bo Zhang +Date: Wed, 18 Apr 2018 11:12:32 +0200 +Subject: [PATCH] Use Lookup to invoke defineClass on Java 9+ (#4976) + +Use Lookup to invoke defineClass on Java 9+ +--- + .../classloader/ClassLoaderUtils.java | 95 ++++++++++++++----- + .../classloader/ClassLoaderUtilsTest.groovy | 41 ++++++++ + .../child/WorkerProcessClassPathProvider.java | 59 +++++++----- + 3 files changed, 146 insertions(+), 49 deletions(-) + create mode 100644 subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/ClassLoaderUtilsTest.groovy + +diff --git a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +index f0a67d6df960..3995ad38be55 100644 +--- a/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java ++++ b/subprojects/base-services/src/main/java/org/gradle/internal/classloader/ClassLoaderUtils.java +@@ -15,51 +15,41 @@ + */ + package org.gradle.internal.classloader; + ++import org.gradle.api.JavaVersion; + import org.gradle.internal.Cast; + import org.gradle.internal.UncheckedException; + import org.gradle.internal.concurrent.CompositeStoppable; + import org.gradle.internal.reflect.JavaMethod; +-import org.gradle.internal.reflect.JavaReflectionUtil; +-import sun.misc.Unsafe; + + import javax.annotation.Nullable; + import java.io.IOException; +-import java.lang.reflect.Field; +-import java.net.MalformedURLException; ++import java.lang.invoke.MethodHandle; ++import java.lang.invoke.MethodHandles; ++import java.lang.invoke.MethodType; + import java.net.URL; + import java.net.URLConnection; + +-public abstract class ClassLoaderUtils { +- +- private static final Unsafe UNSAFE; +- +- static { +- try { +- Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); +- theUnsafe.setAccessible(true); +- UNSAFE = (Unsafe) theUnsafe.get(null); +- } catch (NoSuchFieldException e) { +- throw new RuntimeException(e); +- } catch (IllegalAccessException e) { +- throw new RuntimeException(e); +- } +- } ++import static org.gradle.internal.reflect.JavaReflectionUtil.method; ++import static org.gradle.internal.reflect.JavaReflectionUtil.staticMethod; + ++public abstract class ClassLoaderUtils { ++ private static final ClassDefiner CLASS_DEFINER; + private static final JavaMethod GET_PACKAGES_METHOD; + private static final JavaMethod GET_PACKAGE_METHOD; + + static { ++ CLASS_DEFINER = JavaVersion.current().isJava9Compatible() ? new LookupClassDefiner() : new ReflectionClassDefiner(); + GET_PACKAGES_METHOD = getMethodWithFallback(Package[].class, new Class[0], "getDefinedPackages", "getPackages"); +- GET_PACKAGE_METHOD = getMethodWithFallback(Package.class, new Class[] {String.class}, "getDefinedPackage", "getPackage"); ++ GET_PACKAGE_METHOD = getMethodWithFallback(Package.class, new Class[]{String.class}, "getDefinedPackage", "getPackage"); + } + + private static JavaMethod getMethodWithFallback(Class clazz, Class[] params, String firstChoice, String fallback) { + JavaMethod method; + try { +- method = JavaReflectionUtil.method(ClassLoader.class, clazz, firstChoice, params); ++ method = method(ClassLoader.class, clazz, firstChoice, params); + } catch (Throwable e) { + // We must not be on Java 9 where the getDefinedPackages() method exists. Fall back to getPackages() +- method = JavaReflectionUtil.method(ClassLoader.class, clazz, fallback, params); ++ method = method(ClassLoader.class, clazz, fallback, params); + } + return method; + } +@@ -85,8 +75,6 @@ public static void disableUrlConnectionCaching() { + URL url = new URL("jar:file://valid_jar_url_syntax.jar!/"); + URLConnection urlConnection = url.openConnection(); + urlConnection.setDefaultUseCaches(false); +- } catch (MalformedURLException e) { +- throw UncheckedException.throwAsUncheckedException(e); + } catch (IOException e) { + throw UncheckedException.throwAsUncheckedException(e); + } +@@ -101,6 +89,63 @@ public static void disableUrlConnectionCaching() { + } + + public static Class define(ClassLoader targetClassLoader, String className, byte[] clazzBytes) { +- return Cast.uncheckedCast(UNSAFE.defineClass(className, clazzBytes, 0, clazzBytes.length, targetClassLoader, null)); ++ return CLASS_DEFINER.defineClass(targetClassLoader, className, clazzBytes); ++ } ++ ++ private interface ClassDefiner { ++ Class defineClass(ClassLoader classLoader, String className, byte[] classBytes); ++ } ++ ++ private static class ReflectionClassDefiner implements ClassDefiner { ++ private final JavaMethod defineClassMethod; ++ ++ private ReflectionClassDefiner() { ++ defineClassMethod = method(ClassLoader.class, Class.class, "defineClass", String.class, byte[].class, int.class, int.class); ++ } ++ ++ @Override ++ public Class defineClass(ClassLoader classLoader, String className, byte[] classBytes) { ++ return Cast.uncheckedCast(defineClassMethod.invoke(classLoader, className, classBytes, 0, classBytes.length)); ++ } ++ } ++ ++ private static class LookupClassDefiner implements ClassDefiner { ++ private final Class methodHandlesLookupClass; ++ private final JavaMethod methodHandlesLookup; ++ private final JavaMethod methodHandlesPrivateLookupIn; ++ private final JavaMethod lookupFindVirtual; ++ private final MethodType defineClassMethodType; ++ ++ private LookupClassDefiner() { ++ try { ++ methodHandlesLookupClass = Class.forName("java.lang.invoke.MethodHandles$Lookup"); ++ } catch (ClassNotFoundException e) { ++ throw new RuntimeException(e); ++ } ++ methodHandlesLookup = staticMethod(MethodHandles.class, methodHandlesLookupClass, "lookup"); ++ methodHandlesPrivateLookupIn = staticMethod(MethodHandles.class, methodHandlesLookupClass, "privateLookupIn", Class.class, methodHandlesLookupClass); ++ lookupFindVirtual = method(methodHandlesLookupClass, MethodHandle.class, "findVirtual", Class.class, String.class, MethodType.class); ++ defineClassMethodType = MethodType.methodType(Class.class, new Class[]{String.class, byte[].class, int.class, int.class}); ++ } ++ ++ /* ++ This method is equivalent to the following code but use reflection to compile on Java 7: ++ ++ MethodHandles.Lookup baseLookup = MethodHandles.lookup(); ++ MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(ClassLoader.class, baseLookup); ++ MethodHandle defineClassMethodHandle = lookup.findVirtual(ClassLoader.class, "defineClass", defineClassMethodType); ++ handle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length)); ++ */ ++ @Override ++ public Class defineClass(ClassLoader classLoader, String className, byte[] classBytes) { ++ Object baseLookup = methodHandlesLookup.invoke(null); ++ Object lookup = methodHandlesPrivateLookupIn.invoke(null, ClassLoader.class, baseLookup); ++ MethodHandle defineClassMethodHandle = (MethodHandle) lookupFindVirtual.invoke(lookup, ClassLoader.class, "defineClass", defineClassMethodType); ++ try { ++ return Cast.uncheckedCast(defineClassMethodHandle.bindTo(classLoader).invokeWithArguments(className, classBytes, 0, classBytes.length)); ++ } catch (Throwable throwable) { ++ throw new RuntimeException(throwable); ++ } ++ } + } + } +diff --git a/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/ClassLoaderUtilsTest.groovy b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/ClassLoaderUtilsTest.groovy +new file mode 100644 +index 000000000000..6389f4f02529 +--- /dev/null ++++ b/subprojects/base-services/src/test/groovy/org/gradle/internal/classloader/ClassLoaderUtilsTest.groovy +@@ -0,0 +1,41 @@ ++/* ++ * Copyright 2018 the original author or authors. ++ * ++ * Licensed 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.gradle.internal.classloader ++ ++import spock.lang.Specification ++ ++import java.nio.file.Files ++ ++class ClassLoaderUtilsTest extends Specification { ++ def 'can inject classes to a classloader'() { ++ given: ++ Class testClass = DefaultClassLoaderFactoryTestHelper ++ File classpath = ClasspathUtil.getClasspathForClass(testClass) ++ File classFile = new File(classpath, testClass.name.replace('.', '/') + '.class') ++ byte[] bytes = Files.readAllBytes(classFile.toPath()) ++ MyClassLoader myClassLoader = new MyClassLoader() ++ ++ when: ++ Class klass = ClassLoaderUtils.define(myClassLoader, DefaultClassLoaderFactoryTestHelper.name, bytes) ++ ++ then: ++ !testClass.classLoader.is(myClassLoader) ++ klass.classLoader.is(myClassLoader) ++ } ++} ++ ++class MyClassLoader extends ClassLoader {} +diff --git a/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java b/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java +index 9a7fd911c78f..c1324a04fef5 100644 +--- a/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java ++++ b/subprojects/core/src/main/java/org/gradle/process/internal/worker/child/WorkerProcessClassPathProvider.java +@@ -18,6 +18,7 @@ + + import org.gradle.api.Action; + import org.gradle.api.GradleException; ++import org.gradle.api.JavaVersion; + import org.gradle.api.internal.ClassPathProvider; + import org.gradle.api.specs.Spec; + import org.gradle.cache.CacheRepository; +@@ -57,7 +58,9 @@ + import java.io.InputStream; + import java.net.URL; + import java.util.Arrays; ++import java.util.HashSet; + import java.util.List; ++import java.util.Set; + import java.util.zip.ZipEntry; + import java.util.zip.ZipOutputStream; + +@@ -116,32 +119,9 @@ public void execute(PersistentCache cache) { + try { + File jarFile = jarFile(cache); + LOGGER.debug("Generating worker process classes to {}.", jarFile); +- +- // TODO - calculate this list of classes dynamically +- List> classes = Arrays.asList( +- GradleWorkerMain.class, +- BootstrapSecurityManager.class, +- EncodedStream.EncodedInput.class, +- ClassLoaderUtils.class, +- FilteringClassLoader.class, +- FilteringClassLoader.Spec.class, +- ClassLoaderHierarchy.class, +- ClassLoaderVisitor.class, +- ClassLoaderSpec.class, +- SystemClassLoaderSpec.class, +- JavaReflectionUtil.class, +- JavaMethod.class, +- GradleException.class, +- NoSuchPropertyException.class, +- NoSuchMethodException.class, +- UncheckedException.class, +- PropertyAccessor.class, +- PropertyMutator.class, +- Factory.class, +- Spec.class); + ZipOutputStream outputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(jarFile))); + try { +- for (Class classToMap : classes) { ++ for (Class classToMap : getClassesForWorkerJar()) { + remapClass(classToMap, outputStream); + } + } finally { +@@ -152,6 +132,37 @@ public void execute(PersistentCache cache) { + } + } + ++ private Set> getClassesForWorkerJar() { ++ // TODO - calculate this list of classes dynamically ++ List> classes = Arrays.asList( ++ GradleWorkerMain.class, ++ BootstrapSecurityManager.class, ++ EncodedStream.EncodedInput.class, ++ ClassLoaderUtils.class, ++ FilteringClassLoader.class, ++ ClassLoaderHierarchy.class, ++ ClassLoaderVisitor.class, ++ ClassLoaderSpec.class, ++ SystemClassLoaderSpec.class, ++ JavaReflectionUtil.class, ++ JavaMethod.class, ++ GradleException.class, ++ NoSuchPropertyException.class, ++ NoSuchMethodException.class, ++ UncheckedException.class, ++ PropertyAccessor.class, ++ PropertyMutator.class, ++ Factory.class, ++ Spec.class, ++ JavaVersion.class); ++ Set> result = new HashSet>(classes); ++ for (Class klass : classes) { ++ result.addAll(Arrays.asList(klass.getDeclaredClasses())); ++ } ++ ++ return result; ++ } ++ + private void remapClass(Class classToMap, ZipOutputStream jar) throws IOException { + String internalName = Type.getInternalName(classToMap); + String resourceName = internalName.concat(".class");