LoginSignup
34
35

More than 3 years have passed since last update.

GradleでJavaのビルド時にJDKを動的に切り替える方法

Posted at

はじめに

OpenJDK11 が 2018 年の 9 月にリリースされました。エンタープライズな案件で Java を使うとすると JDK11 が多いのではないでしょうか。
また、すでに JDK8 を使っているけど、新しく導入される一部のプロジェクトでは JDK11 を採用したい、という声もちらほら聞きます。

今回は JDK8 を使っているが JDK11 での検証を始めたときに、Gradle でのビルドを JDK8 と JDK11 の両方に対応したい(ビルドしたい)という場合に、どのようなビルド設定がよいのか考えました。なお JDK の変更にバージョンアップに伴うアプリケーションの修正、チューニングなどは、必要事項と思いますが、本記事からは除きます。あくまでビルド時に JDK を動的に切り替える方法に焦点を当てたいと思います。

設定内容

1. build.gradlesourceCompatibility, targetCompatibility でパラメータを指定

JDK のバージョンについては build.gradle に固定値で指定していることが多いと思います。(あるいは gradle.properties に記載)

以下のようなイメージです。

build.gradle
...

sourceCompatibility = 1.8
targetCompatibility = 1.8

...

あるいは gradle.properties に値を記載しているとすると

build.gradle
...

sourceCompatibility = javaVersion
targetCompatibility = javaVersion

...
gradle.properties
...
javaVersion=1.8
...

というイメージです。

ビルド実行時に動的に切り替えたいので、 build.gradle の定義は

build.gradle
...

sourceCompatibility = javaVersion
targetCompatibility = javaVersion

...

と変数で定義しておきます。

2. ビルド時にパラメータで JDK のバージョンと JAVA_HOME を設定

gradle-Pkey=value でパラメータを指定できます。これを利用して、gradle build -PjavaVersion=1.11 などとすればビルド実行時に JDK のバージョンを指定できます。合わせて Gradle が用いる JDK を指定する必要があります。これは org.gradle.java.home パラメータで指定することができます。

よって

gradle build -PjavaVersion=1.11 -Dorg.gradle.java.home="C:\java\11 --info"

のようにすれば良いのではないでしょうか。

確認

プロジェクト構成

以下のようなプロジェクト構成にしておきます。

C:
└─src
    └─main
       ├─java
       │  └─sample
       │      └─gradle
       │          └─multiversion
       │              Sample.java
       └─resources
build.gradle
plugins {
    id 'java-library'
}

repositories {
    jcenter()
}

dependencies {
}

sourceCompatibility = javaVersion
targetCompatibility = javaVersion

JDK11 でビルド & 確認

JDK11 でビルドします。

>gradle build -PjavaVersion=1.11 -Dorg.gradle.java.home="C:\java\11"

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

実際にコンパイルされた class ファイルについて javap -v でビルドされたバージョンを確認します。

以下の実行結果からわかるように major version: 55 と JDK11 でビルドされていることがわかります。

C:\workspace\sample-gradle-multiversion>javap -v build\classes\java\main\sample\gradle\multiversion\Sample.class
Classfile /C:/workspace/sample-gradle-multiversion/build/classes/java/main/sample/gradle/multiversion/Sample.class
  Last modified 2019/07/12; size 576 bytes
  MD5 checksum 580cd2384cb91a31c14e09339617ba75
  Compiled from "Sample.java"
public class sample.gradle.multiversion.Sample
  minor version: 0
  major version: 55
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #5                          // sample/gradle/multiversion/Sample
  super_class: #6                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // Hello world.
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // sample/gradle/multiversion/Sample
   #6 = Class              #27            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lsample/gradle/multiversion/Sample;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               Sample.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = Class              #28            // java/lang/System
  #22 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #23 = Utf8               Hello world.
  #24 = Class              #31            // java/io/PrintStream
  #25 = NameAndType        #32:#33        // println:(Ljava/lang/String;)V
  #26 = Utf8               sample/gradle/multiversion/Sample
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public sample.gradle.multiversion.Sample();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lsample/gradle/multiversion/Sample;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello world.
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 10: 0
        line 12: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "Sample.java"

JDK 11 でビルドした class ファイルを削除するために gradle clean しておきます。

C:\workspace\sample-gradle-multiversion>gradle clean -PjavaVersion=1.11

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

JDK8 でビルド & 確認

次に JDK8 でビルドします。

C:\workspace\sample-gradle-multiversion>gradle build -PjavaVersion=1.8 -Dorg.gradle.java.home="C:\java\8"

BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed

class ファイルを確認します。 major version: 52 と JDK8 でビルドされていることがわかります。

C:\workspace\sample-gradle-multiversion>javap -v build\classes\java\main\sample\gradle\multiversion\Sample.class
Classfile /C:/workspace/sample-gradle-multiversion/build/classes/java/main/sample/gradle/multiversion/Sample.class
  Last modified 2019/07/12; size 576 bytes
  MD5 checksum ea23dd24700da60b773d93f8ff2f9d77
  Compiled from "Sample.java"
public class sample.gradle.multiversion.Sample
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #5                          // sample/gradle/multiversion/Sample
  super_class: #6                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // Hello world.
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // sample/gradle/multiversion/Sample
   #6 = Class              #27            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lsample/gradle/multiversion/Sample;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               Sample.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = Class              #28            // java/lang/System
  #22 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #23 = Utf8               Hello world.
  #24 = Class              #31            // java/io/PrintStream
  #25 = NameAndType        #32:#33        // println:(Ljava/lang/String;)V
  #26 = Utf8               sample/gradle/multiversion/Sample
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public sample.gradle.multiversion.Sample();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lsample/gradle/multiversion/Sample;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello world.
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 10: 0
        line 12: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "Sample.java"

結論

  1. build.gradlesourceCompatibility, targetCompatibility に変数で定義
  2. Gradleのビルド時にパラメータ -P で JDK のバージョンと -Dorg.gradle.java.homeJAVA_HOME を設定
34
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34
35