Javaがまだ使われている本当の理由は私たちの慣性だけなのか


概要

この記事では『Javaが未だに使われ続ける本当の理由』を技術的観点から深掘りします。C#との比較を通して、言語設計の哲学的差異や実務でのトレードオフについて考えてみましょう。個人的にはLINQのエレガントさに惚れつつも、Javaコミュニティの堅実さには学ぶところが多いと感じています。 要点のまとめ:

  • Javaが依然として広く使われる背景には、既存システムの慣性だけでなく、JVMの成熟したエコシステムやクロスプラットフォーム互換性といった技術的優位点も存在します。特に大規模なエンタープライズ環境では、Javaの安定性が重要な選択理由に。
  • C#の構造体(struct)と自動実装プロパティはメモリ効率とコード簡潔さで優位ですが、Javaの参照型モデルはオブジェクト指向設計において一貫性を保つという哲学的な選択でもあります。例えば小さなPersonデータを扱う際、C#ならスタック活用でパフォーマンス向上が見込めます。
  • LINQとStream APIの比較からわかるように、C#はデータ操作の表現力に重点を置いている一方、Javaは明示的な処理フローを重視する傾向があります。実際にユーザーフィルタリングコードを見比べると、C#版の方が直感的な記述が可能です。
結局のところ言語選択は単なる技術比較ではなく、プロジェクトの文脈やチームの歴史と深く結びついた総合判断なのですね。

Javaが三十歳の誕生日ケーキのろうそくを吹き消す頃、技術の変遷を優雅に乗り越えた言語として祝福されるかと思いきや……どこかしわくちゃな古びた存在が、まだなんとか生き残っている感じだ。確かに「一度書けばどこでも動く」という約束で生まれ、エンタープライズソフトやモバイルアプリ(あのAndroidのおかげもあるけど)、レガシーシステムで今も幅を利かせている。でも、何故か開発者からは愚痴が絶えず、経済的にも頭を抱える場面が多い。チームリーダーとして、多言語使いが集まった中で、それでもどうしてJavaは王冠を守り続けられるのだろう?その座はむしろ惰性というか、新しいものへの革新というよりは重みで保っているようにも見える。C#やマイクロソフト系スタックがもっと親しみやすそうに手招きしているのに……。

ところで、開発者側からするとJavaってまるで片手だけで運転するようなもの。頼りにはなるけど、その間ずっとハンドル握る手に力入れっぱなしみたいな感覚だよね。メモリ管理なんて特にそう。

C#では、構造体(struct)を使うことでスタック上に効率よくデータを置けるし、ガベージコレクターも必要に応じて促せる感じだ。一方、Javaはプリミティブ以外はほぼ全部参照型で、ヒープが膨らみがちでJVMのゴミ集めの挙動に開発者が振り回されることもあるみたい。

例えば、こんなC#のクラス定義。自動実装されたプロパティでゲッターとセッターをサクッとまとめてて便利。

public struct Person
{
public string Name { get; set; }
public int Age { get; set; }

public Person(string name, int age)
{
Name = name;
Age = age;
}

public override string ToString() => $"{Name}, Age: {Age}";
}


これと同じことやろうとするとJavaだと結構長くなってしまう。しかもJavaのクラスは常に参照型だから…

public class Person {

private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return name + ", Age: " + age;
}
}


やっぱりC#のほうがスリムで管理もしやすい印象あるね。Personのような小さく軽量なデータなら構造体としてスタック上に置いておけるからヒープへの負荷減らせそう。リストとかに入れても値型のままで、そのぶんオブジェクト参照分の余計なメモリ消費も抑えられる感じ。

あと、自動実装プロパティのおかげでコードがごちゃごちゃしないしね—カプセル化もしっかりできてるし。

そしてLINQについても触れとかないと。C#使う人たちはWhereやOrderBy、それにクエリ文法とか結構詩的だって言って楽しんでる。でもJavaはStream APIがあるけど…正直道具としてはちょっと切れ味鈍いノコギリ渡されたような感じ?

たとえばユーザー一覧から年齢が二十五歳超えてる人だけ抽出するLINQコード:

var olderUsers = users.Where(u => u.Age > 25);

Console.WriteLine("Users older than 25:");
foreach (var user in olderUsers)
{
Console.WriteLine($"{user.Name}, Age: {user.Age}");
}


一方、Java版はこんなふうになる:

List<User> olderUsers = users.stream()
.filter(u -> u.getAge() > 25)
.collect(Collectors.toList());

System.out.println("Users older than 25:");
olderUsers.forEach(System.out::println);


見た目にもわかる通りC#のLINQはシンプルというか一体感あるし扱いやすい印象かな…。まあStream APIも悪くはないけどどうも心地よさには欠ける気がする、そんな感じかなぁ。
視点の拡張比較:
要素詳細
企業名スタッフメトリック
所在地オースティン
従業員数約150人
契約社員数約40人
Oracleの新ライセンス体系従業員一人ひとりに対する課金モデル
年間Java費用の変化$50,000から$500,000以上へ急増見込み
CFOの反応大打撃、コスト増加に納得できない
影響を受けた部門全社的、特に開発チームと営業チーム
代替技術の提案C#やPythonが注目されている理由はコスト透明性と優しさ

開発者がJavaを使うとき、片手を縛られているような感覚に陥る理由

メソッド構文のWhereを使うか、あるいはクエリ構文のfrom...whereを使うかは、まあ自然で簡潔に感じる。言語自体がその操作をスムーズにサポートしているような。たとえばラムダ式のu => u.Age > 25はプロパティに直接アクセスしていて、それがすごく直感的だし。遅延実行っていう仕組みもあって、もっと処理をチェーンできるけど、そのときすぐコストがかからないんだよね。一方でJavaのStream APIは、確かJava8くらいからだけど、必要なことはできるものの、なんとなく後付け感が否めない。stream()呼んで、それからfilterして、最後にcollectって三段階も踏むし。C#なら一回の呼び出しで全部包み込んじゃう感じなのに。またJavaはgetter(u.getAge()とか)に頼りすぎてて冗長な印象もあるし、LINQみたいなクエリ構文が無いせいか宣言的スタイルにはちょっと遠い気もする。

それで非同期プログラミングになると話がまた変わってくる。C#のasync/awaitはもう夢みたいな存在だけど、JavaのCompletableFutureはなんというか…科学実験失敗したみたいな見た目で扱いづらそうだった気がするんだよね。

かつて、ある開発者が一週間にわたりJavaの並行処理モデルと格闘した末、私のオフィスに駆け込んできて「もう二度と90年代のVBアプリをデバッグするほうがマシだ」と呟いたことがありました。C#のGetUserNameAsyncは次のようにシンプルで直感的な使い方が可能です。

public class UserService
{
public async Task<string> GetUserNameAsync(int userId)
{
await Task.Delay(2000);
return $"User-{userId}";
}

// 使用例
public static async Task Main()
{
var service = new UserService();
Console.WriteLine("ユーザー情報を取得中...");
string userName = await service.GetUserNameAsync(42);
Console.WriteLine($"取得結果: {userName}");
}
}


これに比べると、より冗長で取っつきにくい実装例はこちらです。

public class UserService {
public CompletableFuture<String> getUserNameCompletableFuture(int userId) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
return "User-" + userId;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "Error";
}
});
}

// 使用例
public static void main(String[] args) throws Exception {
UserService service = new UserService();
System.out.println("ユーザー情報を取得中...");
CompletableFuture<String> future = service.getUserNameCompletableFuture(42);
future.thenAccept(userName -> System.out.println("取得結果: " + userName));

Thread.sleep(3000);
}
}


C#のasync/awaitは可読性やシンプルさで圧倒的な勝利を収めています。非同期処理が言語仕様として統合されているため、開発者はまるで同期処理を書いているかのようにコードを書けますし、その裏側でスレッド管理も自動的に行われます。一方、JavaのCompletableFutureは確かに進歩しており、ノンブロッキングなコールバックやチェーン処理を提供しますが、それはあくまで後付けされたライブラリ機能です。ラムダ式やスレッド調整を駆使しながら操作しなければならず、その点ではC#の優雅さには遠く及びません。

開発者視点で見ると、その差は明らかです。C#はまるで頼れる相棒のような存在ですが、Javaの非同期ツールは道具箱から自分で部品を組み立てる必要がある工具セットという印象。機能としては十分でも、決して使いやすいとは言えません。

さらに言えば、Visual Studioなど優れた開発環境も手伝って、C#はより快適な体験を提供しています。一方でJavaには技術的な古臭さ(技術的負債とも言えます)が残っていて、それでもなお多くの現場で使われ続けている理由が不思議になるほどです。

### 会計担当者たちの嘆き:Oracleによる複雑怪奇なライセンス体系と金銭面での悩み

開発者がイライラしているだけならまだしも、お金を握る側――つまり経営層や財務担当者たちは怒り心頭です。その理由も納得できます。OracleによるJava管理体制のおかげで、かつて無料だったこの言語環境が今では費用面で罠だらけになってしまったからです。

LINQ対Stream API - どちらが本当の開発者フレンドリーか

Java SEのユニバーサルサブスクリプションに切り替わったことで、無料だったはずが一気に「従業員ごとに支払い」って感じになって、企業側はかなりビックリしてるみたい。たとえば、ある中規模の製造業のお客さんがいて…あの人たちのJavaコストがまるで一晩で何倍にも膨れ上がったとか。Oracleがライセンスをプロセッサ単位から頭数ベースに変えちゃったせいで、インターン一人ひとりまでカウントされてしまう始末。なんだか、ラップトップ持ってるだけで請求書の行になるって話も聞いたな。

それから、昔使ってたけどもう放置してたソフトウェアに対する遡及的な料金請求もやばいらしい。Oracleはダウンロードやアップデートをしつこく監視してて、何年も前に止めたアプリでも突然「使ってましたよね?」って六桁くらい(多分)請求してくることもあるとか。私が相談したCFOさんもコーヒー飲んでて思わずむせそうになったみたいだし、そのレガシーアプリなんて2018年くらいから触ってないらしいのに…。まあ、このへんは本当にタイミングとか運次第なのかもしれないけど、とにかく驚きしかないという話だよね。

オースティンにある中規模のソフト開発会社、スタッフメトリック。ここは十年ほど前から堅牢なエンタープライズソリューションを提供してきたらしく、その基盤にはずっとJavaがあったみたいだ。社員は百数十人、契約社員が四十人くらい、それに外部のコンサルや代理店もちらほらいるとか。昔から「一度書けばどこでも動く」っていうJavaの魅力で使い続けてきたそうだが……2024年初め頃、不意にOracleのJavaライセンス体系が変わったせいで、かなり頭を抱えている様子。

どうもOracleは、新しい「Java SEユニバーサルサブスクリプション」なるものを導入したらしい。それまでのプロセッサ単位課金じゃなくて、なんと「従業員一人ひとり」に対して料金を取る方式に切り替えたようだ。ただその通知メールは2023年末ごろCTOのマリア・バルデスさんに届いたものの、その時点ではまだピンと来なかったらしい。しかし数ヶ月後、監査通知が来て状況が明らかになったという話。

監査結果によると、Oracleは社内だけじゃなく契約者や外部コンサル、それどころか第三者代理店まで含めて全員カウントしろ、と言っているようだ。しかも直接Javaを触ってなくても関係なしとか。そのため会議室ではバルデス氏が報告書をドン!と叩きつけ、「ユーザー数やサーバー台数関係なく、とにかく全員分払えということ」と説明したそうで、その瞬間みんなシーンとなったんだとか。

ちなみに年間Java費用は今まで五万ドル程度だったものが、一気にその十倍近くにも跳ね上がる見込みとのこと。CFOのデイビッド・グエンさんは「まさかの大打撃」と表現しつつも、「実際には限られたサーバー上だけで動いているんだから、この費用増加は納得できない」と呟いたとか。でも具体的な数字やタイミングはちょっと曖昧で、正確にはもう少し違うかもしれない……そんな感じだった。

Oracleのライセンス変更が企業に与えた財務的な打撃とは

スタッフメトリック社の社員は大体百数十人くらいで、マーケティングや人事、営業チームもいて、彼らはコードなんてほとんど触ったことがない。それなのに、Oracleの新しいモデルでは、その全員をカウントしなきゃならなくなってしまったらしい。さらに、短期的にUIプロジェクトを担当していた数十人ぐらいの契約社員も加わる。外部のクライアント対応エージェントもほんの数人いるとかで、そのせいで請求額が一気に膨れ上がったみたいだ。

「これって利用価値とか関係ないよね」とNguyenさんは怒り心頭だった。どうやらOracleは企業のエコシステムを無視して、とにかく金儲け第一主義で動いているらしい。「ただの早急な金集めだ」とまで言っていた。スタッフメトリック側としてはこの変更は単なる不快感を超えて受け入れ難かったようだ。

以前まではライセンス費用はサーバー台数に合わせたものだったので、予算立ても割と安定していたらしい。でも今度導入された従業員単位の課金方式は、とくにプロジェクトごとに人数が結構変動するから見通しがつかない感じになってしまったみたいだ。

Maria Valdezさんによると、ある時Oracleの営業担当者から「クラウドサービスへのアップグレード」を勧められたそうだ。それも料金負担軽減になるという話だったけど、「売り込み臭しかしない」と思わず呟いてしまうほどだったとか。「頼りにしてたツールが罠になっちゃった」みたいな言い方もあった。

しかも契約条項はすごく複雑で曖昧で、Oracleの監査プロセス自体も怖かったそう。実際にはもう二年くらい前に使わなくなったソフトウェアについて遡及的な請求までされて、本当に泣きそうになったと言う声も聞いた。

影響はすぐ出てきて、技術的な問題を抱えながらもJavaを使い続けていた開発者たちが反発した。代替案としてC#やPythonを推す声が増えた理由には、マイクロソフト製品のほうが料金体系が分かりやすくて開発者にも優しいという点があったようだ。

経営陣は、たしかに財務的なダメージで頭を抱えていたみたい。Nguyenによると、そのコストの増加は数十万ドルくらいあって、今年の研究開発予算がほぼ吹き飛ぶかもしれないとか。イノベーションが止まっちゃう恐れもあるって話だったけど、正直どうなるかはまだ曖昧。

全社集会ではCEOのRachel Patelが社員にこう言ったらしい。「Javaには成長のパートナーとして期待していたけど、利益をむしり取る寄生虫だったとは…Oracleの欲深さで私たちはすべてを見直さざるを得なくなった」とか。そんな感じで、Staffmetricは急いで移行計画を立て始めて、OpenJDKにすぐ逃げられるか試したり、新規プロジェクトにはC#も使ってみたりしたそうだ。これがコスト削減だけじゃなくて、Javaの重荷から解放されることでチームの士気アップにもつながったようだ。

結局Oracleのライセンス改定は利用者からすると締め付けが強すぎてショックだったみたい。経営陣の怒りも大勢の意見と同じで、「Java自体の価値向上なんてどうでもよくて、とにかく金儲けに走っている」感が拭えなかったとか。その事件はStaffmetricにとって目覚めというか、「30年も続いてきた言語でも、その管理者次第では足枷になる」という痛烈な教訓になったようだ。

それで会社はOracleから離れる決断を固めたわけだけど、その終わり方は派手じゃなくて「かなり高くついた地味な幕引き」みたいなものだったと言われている。

ところで監査に関してだけど…Oracleの厳しさが一番出る場面らしい。例えば最初は営業担当から軽く「非公式監査」が来て、それが何となく不文律っぽいルールへの示唆なんだけど、その後突然本格的な調査が入って「違反発見!」と騒ぎ立てられるパターン。誰かが冗談めかして言ってたんだよね、「Oracleと仕事するのは、相手が自分のカード全部知っていて、更に銃まで隠し持ってるポーカーやってるようなものだ」って。

まあそんな感じで色々あったんだけど、本当に怖いというか面倒くさいことこの上ないらしいよ…

Oracleの監査が企業にとってなぜ悪夢のような体験なのか

ライセンスの話、もう迷路みたいでさ。暗号解読者でも挫折しそうなほどの専門用語の山があって、JDKとJREとかクラウドの条件とか例外規定とか、何が守られてるかなんて法務チームなしじゃ全然わからない。実際に経理部門が会議中に「もう無理!」って手を挙げちゃうこともあるし、Oracleの透明性は泥みたいに濁ってる感じ。 

一方でマイクロソフトのスタックは、料金も割と予測しやすいし、契約内容もシンプルだし、「パートナー生態系」も搾取感がそんなにない印象あるよね。Javaの場合は価値よりもOracleのお金儲け主義が前面に出てて、多くの組織がなんでまだこの巨大なシステムに縛られてるんだろうって疑問持ち始めてる。

さて、Javaがどうやって約三十年くらいずっと人気を保ってきたかというと…古くからあるシステム群や膨大なエコシステム、それとAndroid依存がそれっぽい。でもクライアント先を見ると、C#なら開発者は満足度高そうだし運用コストも低め、それにベンダーも変な圧力かけてこない感じだから、このJava支配は「埋没費用錯覚」的なものじゃないかなと思えてしまうんだよね。

技術者側はもっと新しいツールを求めている気配だし、お金回りを管理する人たちはもっと安定感を欲しているみたい。ただこのまま流され続ける理由はいろいろあって…まあ完全には見えづらいけど…。

Javaはどこにもない、なのにまるで帰りたくないパーティーの客みたいにしぶとく残ってる。そういえば、「なぜJavaじゃないの?」って聞くよりも、「もっとマシなものは何?」って考えたほうがいいかもしれない。だって、三十年近くもこんな感じの中年の迷走を見てきてるわけで…ちょっと長すぎる気もするよね。

ここまで読んでくれてありがとう。ついでに言うと、

- もしよかったら、作者に拍手とかフォローをぜひ!👏
- あとTwitter(今はX?)、BlueSky、Truth Social、それからSubstackやLinkedInでも追いかけてみてね。

そんな感じかな、まあまたいつか…

参考記事

新しい現場の使用言語がjavaなのですが - Yahoo!知恵袋

新しい現場の使用言語がjavaなのですが、javaは未経験です。 C++とかC#とかは、5年くらいやっているので、javaの基本文法をサッとネットで見た感じ ...

ソース: Yahoo!知恵袋

まだモダンなプログラミング言語のレースで遅れてる感じ? : r/java

無知。まさに、今のJavaと、Javaが持つ能力について、マジで知らない。 Rust信者たちがRust信者やってる。何でもかんでもRustで書き直せっていう ...

ソース: Reddit · r/java

コラムニスト

エキスパート

関連ディスカッション

❖ 関連記事