Java API 訴訟の件で私が Google よりも Oracle の肩を持つ理由

  • 309
    いいね
  • 8
    コメント

はじめに

Java API を巡って Oracle と Google の訴訟が続いています。世間の論調を見ていると、「Oracle 対 Google」の構図を「プロプライエタリ対オープンソース」と位置付け、あたかも Google が正義の味方であるかのように扱っていますが、この件に関しては、私は逆の立場です。むしろ、「Google けしからん」と思っています。私がそう思う理由をここに書きます。

Java の互換性

Android が登場するずっと前から、業界の皆は、JCP (Java Community Process) に則り、協議の上 Java API の仕様を決めてきました。仕様を策定する際には、RI (Reference Implementation) (リファレンス実装) と TCK (Technology Compatibility Kit) (テスト群) も同時に用意します。これは、策定した仕様が現実的に実装可能であるかどうかを確認するため、および、第三者が仕様に則って実装をおこなったときにその実装の互換性を確認できるようにするためです。

JCP に則った仕様策定作業は時間がかかります。しかし、「Write once, run anywhere」(一度プログラムを書けばどこでも動く) という、Java の大切な理念のため、このプロセスは大事です。今現在も Java API はこのプロセスに則って定められています。Java SE (Java Standard Edition) の API だけにとどまらず、JAX-RS 2.0 (JSR 339) なども JCP で定められた仕様です。

Java の互換性に関して、API が共通化されていることよりも重要なのは、Java アプリケーションを動かすための土台である JVM (Java Virtual Machine) (Java 仮想マシン) の存在です。JVM さえそれぞれの環境に移植しておけば、どこでも Java アプリケーションが動くのです。共通の仮想マシンが無い世界では、CPU (x86, ARM, MIPS, PowerPC, Super-H, ...) と OS (Windows, Linux, VxWorks, Symbian, eCos, ...) の組み合わせ毎にクロス開発環境を用意し、ソースコードをクロスコンパイルすることでそれぞれの環境用にアプリケーションのバイナリを作る必要があります。そして、そのようにして生成されたバイナリは別の環境では動きません。一方、Java アプリケーションを Java コンパイラでコンパイルすると、CPU x OS の組に依存しない形式のバイナリ (Java バイトコード) が生成され、それを JVM が実行することになるので、結果、JVM の下にある CPU x OS が異なっていても、アプリケーションが動きます。もちろん、JVM を実装する人はその下にある CPU x OS の違いを認識する必要がありますが、JVM エンジニアが頑張って CPU x OS の差異を吸収して JVM を実装してくれれば、Java アプリケーションプログラマーは、CPU x OS の差異を気にせずにプログラムを書くことができます。

余談ですが、JVM を実装する際、どうしてもアセンブリ言語で書かなければならない部分があります。それは、Java コードからネイティブ関数を呼ぶときに、JVM 内のスタックに積み上げられた引数群をネイティブ関数が解釈できる形に積み直す部分です。JVM 内では引数は単純にスタック上に積み上げられていますが、ネイティブの世界では、「先頭の幾つかの引数は順番に□□レジスタ群に置き、でも浮動小数点数の引数は××レジスタ群に置き、で、乗り切らないものはアラインメントとバイトオーダーを気にしながらメモリ上のスタックに置く」、というようなルールがあります。このルールに基づいて引数を積み直すわけですが、そのためのコードは C や C++ では書けないので、アセンブリ言語で書くことになります。コード量はたいしたことはないのですが、ちゃんと実装するためには、対象の CPU アーキテクチャを理解し、その CPU 用のアセンブリ言語を勉強し、対象となるバイナリ形式の ABI (Application Binary Interface) 仕様書も読み込まなければならず、コプロセッサの有無で浮動小数点数の扱いも切り替える、といったことをやらないといけません。私も PowerPC や Super-H 等、幾つかの環境に JVM を移植してきましたが、この部分の移植がいつも楽しかったです。想定通り動くと「やったー!」という気分になりました。

Google による互換性の破壊

手間と時間をかけ、業界全体で Java の互換性を大切にし、自由競争に基づく共存共栄の世界を築いていたところに、Android が登場しました。

Android はまず、名前衝突を避けるために定められたパッケージ名の naming convention を完全に無視し、勝手に android というトップレベル・パッケージ名を宣言しました。そして、あろうことか、java.* パッケージや javax.* パッケージの下にあるクラス群やメソッド群も、好き勝手に取捨選択しました。

いやもう、これは私にとっては倫理的に許されないレベルの話でしたし、今でも許してはいないです。特に、当時の組込業界では、CLDC (Connected Limited Device Configuration) (JSR 139) や CDC (Connected Device Configuration) (JSR 218) 等、制限の厳しい環境向けに Java 仮想マシン仕様のサブセットを定めたり、その上に乗せる MIDP 2.0 (Mobile Information Device Profile 2.0) (JSR 118) や PBP (Personal Basis Profile) (JSR 217) 等のプロフィールを定めたりして、苦労して共通仕様を策定してきました。そうすることで、自由競争を促しながら「Write once, run anywhere」を業界全体で大切にしてきました (DoJa という自社都合戦略をとった会社もありましたが)。現実的には「Write once carefully, run anywhere conditionally」(一度プログラムを注意深く書けば条件付きながらどこでも動く) でしたが、業界全体の協力により、携帯端末へのアプリケーション配布など、新しい産業を生み出してきました。しかし、Google は、そういう皆の努力を腕力で破壊したのです。

加えて、元 Java 仮想マシンエンジニアとして納得がいかなかったのは、Android が Java 仮想マシンではなく、似て非なる Dalvik 仮想マシンを採用し、それがまた、後出しのくせに劣化技術だったからです。特に、クラスローディングの仕組みを破壊してしまったため、Java の大きな利点が幾つか失われました。ARM Jazelle のようなハードウェアアクセラレーション技術との連携もありませんでした。

【参考】
- Android で OSGi を使うべきでない理由 (2011年2月15日)
- Android System.exit(int): 驚愕の実装 (2011年3月1日)
- Felix on Android でバンドルがスタートできない問題の回避方法 (2010年12月11日)

Android と Java、それぞれの統制

Android 登場以前までは、業界関係者が皆協力しており、Oracle といえども JCP に則って仕様策定を進めていました。また、今もそうしています。しかし、Android のほうはどうでしょうか? Google の影響を大きく受けており、Android の進化は Google のビジネスの都合に歩調を合わせています。「Google のおかげで Java が自由になる」と思っている人は、自分がどれだけ Google に振り回されているか分かっていないです。おそらく、Android 登場以前の世界を知らないからです。それは自由ではなくて、Google の掌の上です。「Android 新バージョンの発表があると思うから、Google 主催の次のイベントが楽しみ!」と思っている時点で、Google に振り回されていることに気付くべきです。

一方 Oracle は、JCP に則り、エキスパートを集めて Java API の仕様策定作業をしています。時間はかかりますが、Java の新バージョンで追加される言語仕様や API の設計が洗練されているのは、そういう理由です。そして、そのような策定作業を経て定められた仕様に基づく JDK (Java Development Kit) / JRE (Java Runtime Environment) を維持管理して無料で提供している Oracle は、オープンソース界に大きく貢献しています。Hadoop 等のビッグデータソリューションの成功も、高品質な JDK / JRE なくしては成り立ちません。

Oracle 提供の JDK / JRE に比べ、Android の品質はどうでしょうか? こちらは、平気でゴミクズのような API が公式 API として追加されます (参考:Android BLE API及びAndroid Beacon Libraryの設計の酷さを技術的に説明する)。TCK のような互換性維持のためのテストセットもありませんから、String.indexOf(String,int) という基本 API に実装不具合があっても、それを事前に検出できずにリリースが行われることがあります (参考:Android の String.indexOf(String,int) メソッドの不具合)。オープンソースを悪用して (と言ったら言い過ぎかもしれませんけど) JavaDoc を他のオープンソースプロジェクトからコピペし、その Android 用実装が JavaDoc に書かれている機能を満たさない劣化実装になっていても、JavaDoc をそのまま放置したりしています (参考:Solution for gdata-java-client's SAXNotRecognizedException)。

名実共に Java を守っているのは Oracle

「Oracle は自社の利益しか考えていない。一方 Google はオープンソース界の味方」という論調をみかけますが、果たして本当にそうでしょうか?

過去のコミュニティーの知恵と協力の結晶である Java の設計にただ乗りし、自社のビジネス都合で Java の互換性を破壊し、その上で劣化実装を提供する。このようなことをする Google を、どうして「Java の自由を守る正義の味方」と呼べるでしょうか?

名実共に Java を守っているのは Oracle のほうであり、むしろ Google は「Java の破壊者」なのです。

Oracle が「Java API の著作権」を切り口に裁判を起こしているのは、Java の互換性を守らんがため。そうは思いませんか?

補足

本件に限っては「Google けしからん」と思っていますが、個人的に Google 社が嫌いなわけではありません。自社プロダクトである AuthleteGoogle Cloud Platform 上に構築していたりします。

追記

[2016/05/29] 本ブログ記事、想定以上に物議を醸してしまいました (汗)。裁判の論点に何も言及していないのは各所でご指摘を受けている通りです。API 著作権自体については「筋が悪い議論」だと思っていて、特に支持しているわけではありません。API 著作権とフェアユースについては、そんなことを裁判で議論しなければならなくなった状況を嘆いている派です。紳士協定で成り立っていたエコシステムを破壊した上でフリーライドする者が現れたときに、筋の悪い裁判を起こすくらいしか対策が無いことを憂いています。そういうわけで、裁判については、論点ではなく時代背景についてのみ言及しています。あと、私は Oracle 信者ではなく、どちらかと言うと (以下自粛)。

CLDC や CDC が想定していたミニマムスペックが当時の携帯端末の物理性能に比べてあまりに低く、「Multitasking VM や MIDP 3.0 などの議論をやめて、もう J2SE を全部乗っけてしまえばいいのに」と思っていたところに Android が登場しました。ビジネス的には Android が正しく、「時代の要請に応えられなくなりつつあった既存プレイヤー達 vs 破壊的参入者」という構図で、ビジネス書のユースケースとしても良い事例だと思います。

様々なご意見

本記事に対してポジティブなのかネガティブなのかに関係無く、良い論考については、ご本人様の了解を得た上でご紹介させていただきたく思います。

幸いなことに「Javaと偽Javaの話。」を見つけることができましたので、ご本人様の了解の上、ご紹介させていただきます。

よろしくお願い致します。