2億9千万年問題
読み:におくきゅうせんまんねんもんだい
外語:year two hundred ninety million problem
Javaで開発されたアプリケーションの抱える時限爆弾の一つ。
概要
Javaの日時管理は、1970年1月1日00:00:00を基準(これをThe Epochという)とし、その時間からの経過ミリ秒で扱っている。なお、この経過秒数には、一般的には閏秒は含めていない。
この経過ミリ秒数は64ビットで表現されるが、符号を考慮すると有効桁は63ビットしかない。そのため「1970年1月1日 00:00:00 + 0x7fffffffffffffffミリ秒より後が表現できない」という問題を抱える事となった。
即ち、292278994(令和292276976)年8月17日にカウンターはオーバーフローし、時刻は予期せぬ値を指すものと考えられる。これが2億9千万年問題である。
特徴
検証
実際にどうなるのか、Linux上のJava環境で動作を確認してみた。
import java.util.*;
public class test
{
public static void main(String[] args)
{
Date date1 = new Date();
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
date1.setTime(0x7fffffffffffffffL);
System.out.println(date1);
System.out.println(date1.getTime() % 1000L);
date1.setTime(0x8000000000000000L);
System.out.println(date1);
}
}
結果は次の通りだった。
Sun Aug 17 07:12:55 UTC 292278994
807
Sun Dec 02 16:47:04 UTC 292269055
計算が正しければ、2億9227万8994年8月17日(日曜日)の、07:12:55.807(UTC)、16:12:55.807(JST)までしか扱えず、その1ミリ秒後は異常な日時を示すことがわかる。
2000年問題
2000年問題が騒がれた頃、Sun Microsystemsは、Javaには2000年問題は無いと表明していた。
確かに、Javaに2000年問題は存在しないが、これとは別に2億9千万年問題が存在するのである。
先送りの問題
Sun Microsystemsは、2000年問題や、Cのtime_tにある2038年問題をJavaで起こさないよう、日付時刻型の仕様を練り上げたと考えられる。
かくしてJavaの仕様は確かに次の約2億9千万年間の年号表記を保証する。その時には誰も現在のプログラムは使用されていない、のみならず人類も既にいないかも知れない、という前提がある。しかしこれは全く誤った理論であり、現在の2000年問題へと繋がる怠惰なプログラミングの習慣であるといえる。
西暦2億9千万年には誰もが現在のプログラムの消滅を仮定しているが、2000年問題の発生の歴史を見れば、その考え方が誤っていることは自明である。
2000年問題を見据えてJavaは対策を講じはしたが、しかしその解決法は、単に問題を2億9千万年後に先送りしたに過ぎなかったのである。
問題発生は、約2億9千万年後に迫っている。このため、今から心配で夜も眠れない人がいても不思議ではない。
2億9千万年「前」
ちなみに、現在から時間軸を遡り「2億9千万年前」はどうであったかというと、古生代の最後、ペルム紀であった。
当時は人類はもちろん、まだ哺乳類すらいない。この頃から哺乳類の祖先ともいえる両生類が魚類から進化して出現した。
再検索