LoginSignup
14
15

More than 5 years have passed since last update.

Java8 で作られたアプリケーションをJava6で動かす

Last updated at Posted at 2017-06-16

たまたま業務でJava8で作られたアプリケーションをJava6で動かすように修正するような仕事があったので、珍しいことだと思うのでまとめようと思う。
普通このようなことをやることはないと思う…
(そして私はこんな仕事やりたくなかったw)

背景

別のあるプロジェクトで使っていたRestful Java8アプリケーションがあり、
そのアプリケーションを自分のいるプロジェクトに適用しようとしたところ、
アプリケーションの配置先サーバがRed Hat Enterprise Linux 5.1という…

配置先のサーバのOSをバージョン上げてほしかったが、他のアプリケーションが動いているからムリとのこと…

そんなことからJava8 → Java6へのダウングレードを行うことになった。

ついでにWikiによると、Red Hat Enterprise Linux 5.1は2007年11月7日にリリースされた10年もの。
標準サポート期限は2017年3月31日までで既に標準サポート期限は切れている。
延長サポートは2020年11月30日までとなっている…

Java8での仕様変更や追加

Java8で追加された機能の代表的なものをいくつかあげよう。

  • Lambda式
  • メソッド参照
  • Stream API
  • Functional interfaces
  • try-with-resources
  • Interface Default,staticメソッド
  • 日時API(LocalDateTimeなど)

これら以外にも、多くの機能が追加されている。
詳細はリリースノートを見てほしい。

このようにJava8では多くのAPIや記述方法の変更があり、Javaとして非常に変化が大きかった。

Java backporting tools

Java backporting toolsとは、あるバージョンから古いバージョンへJava classファイルを変換するためのプログラムであり、
今回使用したのは以下の2つ。

Retrolambda

RetroLambdaはMaven,Gradleのプラグインで、
ビルドするときにJava8の記述を下位のバージョンへ変換してくれる。
ビルドされたclassファイルを見ると、XXX.classとは別に、XXX$$Lambda$9.classというようなclassファイルが出力されており、
Lambda式などのJava 8の記述は別のクラスファイルとして処理されていることが分かる。

以下は、Retrolambdaで対応しているもの。

  • lambda式
  • メソッド参照
  • try-with-resources
  • Interface Default,staticメソッド(限定サポート)

新しい記述はほぼ全て対応していることになる。

使い方

ここではMavenでの使い方を解説する。Gradleの方はこちらのReadMeを参照。

pom.xmlに以下のように記述する。

            <plugin>
                <groupId>net.orfjackal.retrolambda</groupId>
                <artifactId>retrolambda-maven-plugin</artifactId>
                <version>2.5.1</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>process-main</goal>
                            <goal>process-test</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <target>1.6</target>
                </configuration>
            </plugin>

これでmvnのライフサイクル上で、自動でビルドされるようになる。
configuration.targetは変換後のJavaバージョンを記述する。

開発するとき(IDEなどの設定)は、Java8 SDKを使用して開発し、
ビルドしてできたJarの実行はJava6で行う。

この方法の問題点はJava8のAPIを使用していてもコンパイルできてしまうことである(もちろん実行時にエラーになる)が、
それを警告するようなプラグインも存在するらしい。(自分は未使用)

streamsupport

streamsupportはJava8の新APIを多くカバーしている。
カバーしているものは以下。

  • Streams API
  • CompletableFuture API
  • Parallel array operations
  • Functional interfaces

使い方

pom.xml

pom.xmlのdependenciesに以下を追加する。
(streamsupport.versionはpropertiesに定義。)

        <!-- To use Java8 stream,functional API in Java6 -->
        <dependency>
            <groupId>net.sourceforge.streamsupport</groupId>
            <artifactId>streamsupport</artifactId>
            <version>${streamsupport.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.streamsupport</groupId>
            <artifactId>streamsupport-cfuture</artifactId>
            <version>${streamsupport.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.streamsupport</groupId>
            <artifactId>streamsupport-flow</artifactId>
            <version>${streamsupport.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.streamsupport</groupId>
            <artifactId>streamsupport-atomic</artifactId>
            <version>${streamsupport.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.streamsupport</groupId>
            <artifactId>streamsupport-literal</artifactId>
            <version>${streamsupport.version}</version>
        </dependency>

基本的な使い方

基本的にはjava8 APIと異なるパッケージ名で、同じクラス名、同じメソッド名で呼び出すことができる。

例えばCompletableFuture APIは

import java.util.concurrent.CompletableFuture;

import java8.util.concurrent.CompletableFuture;

のようになる。

Stream APIの使い方

RefStreams.ofでstreamインスタンスを作成できる。


import java8.util.stream.RefStreams;

RefStreams.of("a", "b", "c")
    .map(String::toUpperCase)
    .forEach(System.out::println);

Java 8では以下のようにListクラスにstreamメソッドが追加されている。
この場合は以下のようになる。

import java.util.Arrays;
import java.util.List;

List<String> list = Arrays.asList("a", "b", "c");

list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

import java.util.Arrays;
import java.util.List;
import java8.util.stream.StreamSupport;

List<String> list = Arrays.asList("a", "b", "c");

StreamSupport.stream(list)
    .map(String::toUpperCase)
     .forEach(System.out::println);

所感

これを読んでいる人には、Java8のアプリケーションをJava6へダウングレードするような機会が来ないことを祈ってます。。。

14
15
3

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
14
15