2023/09/19

JEPでは語れないJava 21

このエントリーをはてなブックマークに追加

毎度おなじみ半年ぶりのJavaのアップデートです。

Java 21はLTSのリリースが3年から2年に変わって、はじめてのLTSバージョンです。LTSかどうかはOpenJDK的には関係ないのですが、やっぱりこのバージョンを一区切りとする感じですね。

Java 21のJEPは以下の通り。JEPが15もあり、しかもPreviewもしくはIncubatorではないスタンダードJEPも多いのが、LTSという感じですね。。

  • 430: String Templates (Preview)
  • 431: Sequenced Collections
  • 439: Generational ZGC
  • 440: Record Patterns
  • 441: Pattern Matching for switch
  • 442: Foreign Function & Memory API (Third Preview)
  • 443: Unnamed Patterns and Variables (Preview)
  • 444: Virtual Threads
  • 445: Unnamed Classes and Instance Main Methods (Preview)
  • 446: Scoped Values (Preview)
  • 448: Vector API (Sixth Incubator)
  • 449: Deprecate the Windows 32-bit x86 Port for Removal
  • 451: Prepare to Disallow the Dynamic Loading of Agents
  • 452: Key Encapsulation Mechanism API
  • 453: Structured Concurrency (Preview)

やはり注目はJEP 444: Virtual Threadsでしょうね。すでに、Springなどのフレームワークが対応を発表するなど、Virtual Threadが普及するのも意外に早いかもしれません。とはいうものの、Springなどのフレームワークを使っている場合、ユーザーがVirtual Threadを意識することはないはずです。

Project Amber関連のJEPは5つ。スタンダードJEPはパターンマッチングのJEP 440とJEP 441です。JEP 443などが残っているので、パターンマッチングに関する機能はまだすべてではありません。しかし、switch式でパターンマッチングができるようになったのは大きいと思います。

JEP 430は汎用に使える小さなテンプレートエンジン、JEP 445はmainメソッドの簡略化です。

JEP 431はコレクションに関する機能です。これはAPIなので、java.utilパッケージで説明します。

JEP 439 Generational ZGCはZGCに世代別GCの機能を加えたものです。JEP 442 FFMはThird Previewなので、なかなかスタンダードにならないですが、どうやら次のJava 22でスタンダードになるようです(JEP 454)。FFMと同じProject PanamaのJEP 448 Vector APIもなかなかスタンダードにならないですね。

JEP 446 Scoped ValuesとJEP 453 Structured ConcurrencyはVirtual Threadと同じProject Loomで策定されているAPIです。できれば、これらがまとめてJava 21でスタンダードJEPになればよかったのですが、まぁしかたないです。

JEP 449とJEP 451は機能削減。というか、Windowsの32bit版なんてまだあったのかという感じですねw

JEP 452 Key Encapsulation Mechanism APIはセキュリティ関連のJEPです。

と、軽くJEPを説明したところで、APIの変更について紹介していきましょう。今回はAPIの変更がいっぱいあります。

例によってセキュリティ関連のAPIは省略します。また、java.compilerモジュール、java.desktopモジュールの変更は通常の開発では使用しない変更であるため省略します。

 

廃止になったAPI

Java 21では2クラス、1メソッドが廃止になりました。いずれも、頻繁に使われるAPIではないので、特に問題はないと思います。

クラス

  • java.lang.Compiler
  • javax.management.remote.rmi.RMIIIOPServerImpl

CompilerクラスもRMIIIOPServerImplクラスもJava 9からforRemoval=trueになっていたので、とうとう削除という感じです。

 

メソッド

  • java.lang.ThreadGroup.allowThreadSuspension(boolean)

「allowThreadSuspensionメソッドなんてあったの?」という感じですが、実際には何も処理を行わず、単にfalseを返すだけのメソッドになっています。このメソッドはJ2SE 1.2からDeprecatedになっており、逆になぜ今まで残していたのかが不思議なくらいですね。

 

廃止予定のAPI

Java 21で追加された廃止予定のAPIは、メソッドが2種類です。

 

メソッド

  • javax.management.remote.JMXConnector.getMBeanServerConnection(Subject delgationSubject)
  • javax.swing.plaf.synth.SynthLookAndFeel.load(URL url)

getMBeanServerConnectionメソッドはオーバーロードが2種類あり、引数のある方がforRemoval=trueになりました。Subjectを指定することはまずないと思うので、引数なしのgetMBeanServerConnectionメソッドを使用すれば大丈夫です。

SynthLookAndFeelクラスはSwingのLook&Feelの1つですが、Swingが使われることもないでしょうし、ましてやLook&FeelにSynth Look&Feelを使うことはまずないと思うので、問題ないと思います。

 

追加/変更されたAPI

Java 21で追加されたAPIの半分ぐらいはFFM APIですが、Preview JEPなので省略します。FFM API以外にもPreview APIが含まれていますが、それも省略します。

 

java.base/java.ioパッケージ

java.ioパッケージではAPIの追加はないのですが、変更がありました。

 

Consoleクラス

コンソールを扱うためのConsoleクラスですが、Java 21でsealedクラスになりました。

実をいうと、ConsoleクラスはJava 19まではfinalクラスでしたが、Java 20でfinalではなくなりました。これは、コンソールを扱うためにJLineライブラリを扱うためだったようです。JLineはJShellでも使われている、コンソールを扱うためのライブラリです。

しかし、他の用途でConsoleクラスの派生クラスを作成させるためではありません。そこで、sealedクラスにすることで、実質的にfinalクラスと同じになりました。

ちなみに、permitsされているクラスはProxyingConsoleです。

 

java.base/java.langパッケージ

Virtual Threadの導入によりスレッド関連でAPIの追加が行われています。また、Java 21でサポートされるUnicodeのバージョンは15.0のままなのですが、CharacterクラスにもAPI追加が行われています。

 

Characterクラス

文字の判別メソッドが6種類追加されました。

  • static boolean isEmoji(int codePoint)
  • static boolean isEmojiPresentation(int codePoint)
  • static boolean isEmojiModifier(int codePoint)
  • static boolean isEmojiModifierBase(int codePoint)
  • static boolean isEmojiComponent(int codePoint)
  • static boolean isExtendedPictographic(int codePoint)

今までは絵文字かどうか調べるには、文字がUnicodeのどの面にあるかなど調べなくてはいけなかったのでめんどうくさかったのですが、これで簡単になりました。

なお、Java 21ではUnicodeのバージョンアップはなく、Unicode 15.0のままなので、UnicodeBlockクラスなどは変更ありません。

 

Mathクラス/StrictMathクラス

clampメソッドのオーバーロードが4種類追加されました。

  • static int clamp(long value, int min, int max)
  • static long clamp(long value, long min, long max)
  • static double clamp(double value, double min, double max)
  • static float clamp(float value, float min, float max)

clampメソッドは、valueをminとmaxの間に固定するためのメソッドです。valueがmaxより大きければmaxを返し、minより小さければminを返します。minとmaxの間であればvalueをそのまま返します。

jshell> Math.clamp(1000L, 100L, 200L)
$1 ==> 200

jshell> Math.clamp(1000L, 2000L, 3000L)
$2 ==> 2000

jshell> Math.clamp(1000L, 100L, 2000L)
$3 ==> 1000

jshell>

 

Stringクラス

indexOfメソッドのオーバーロードが4種と、スプリットに関するメソッドが追加されました。

  • int indexOf(int ch, int beginIndex, int endIndex)
  • int indexOf(String str, int beginIndex, int endIndex)
  • String[] splitWithDelimiters(String regex, int limit)

indexOfメソッドは引数が1つものと、beginIndexが指定できるものが提供されていましたが、それに加えてendIndexを指定できるようになりました。

splitWithDelimitersメソッドは、文字列を分割する時に、分割に使用した正規表現を含めて分割します。

jshell> var text = "ab:cd:e::fg"
text ==> "ab:cd:e::fg"

jshell> text.split(":", 100)
$2 ==> String[5] { "ab", "cd", "e", "", "fg" }

jshell> text.splitWithDelimiters(":", 100)
$3 ==> String[9] { "ab", ":", "cd", ":", "e", ":", "", ":", "fg" }

jshell>

これが不思議なのが、privateメソッドでsplit(String regex, int limit, boolean withDelimiters)があるということです。splitWithDelimitersメソッドも内部でこのsplitメソッドをコールしているだけです。

なので、このprivateメソッドをpublicにすれば、わざわざ長ったらしい名前のsplitWithDelimitersメソッドを追加する意味がないと思うんですよね。

 

StringBufferクラス/StringBuilderクラス

StringBufferクラスとStringBuilderクラスは、いずれもAbstractStringBuilderクラスの派生クラスです。AbstractStringBuilderクラスはAppendableインタフェースを実装しているので、StringBuffer/StringBuilderクラスもAppendableインタフェースを実装したクラスになります。

しかし、StringBuffer/StringBuilderクラスのimplements節には記述されていなかったので、Javadocの「すべての実装されたインタフェース」にはAppeendableインタフェースが記載されるものの、implements節の方には記載されていませんでした。そのためなのか、Java 21からimplements節にAppendableインタフェースが追記されました。なお、この変更による動作の変更はありません。

また、repeatメソッドのオーバーロードが2種類追加されました。

  • StringBuilder repeat(int codePoint, int count)
  • StringBuilder repeat(CharSequence cs, int count)

repeatメソッドは文字や文字列を指定した回数だけ繰りかえします。

jshell> var builder = new StringBuilder()
builder ==>

jshell> builder.repeat("a", 10)
$2 ==> aaaaaaaaaa

jshell> builder.toString()
$3 ==> "aaaaaaaaaa"
    
jshell>

とはいうものの、StringBuilderクラスを使う機会は減りましたね。今は、リテラル文字列の連結(たとえば、"a"+"b"のような文字列の連結)もStringBuilderクラスを使ってないですし。ましてや、StringBufferクラスはもうDeprecatedにしてもいいのではないかと思うぐらいですね。

 

Thread.Builderインタフェース

順番的にはThreadクラスの方が先ですが、その内部インタフェースとクラスを先に紹介します。

Thread.BuilderインタフェースはThreadFactoryインスタンスを作成したり、スレッドを作成するためのインタフェースです。もちろん、Virtual Threadの導入により追加されたインタフェースです。

Thread.Builderインタフェースはsealed interfaceで、Thread.Builder.ofPlatformクラス、Thread.Builder.ofVirtualクラスだけが派生クラスとして定義されています。これらの実装クラスは後述します。

Thread.Builderインタフェースで定義されているメソッドは以下のとおり。

  • Thread.Builder name(String name)
  • Thread.Builder name(String prefix, long start)
  • Thread.Builder inheritInheritableThreadLocals(boolean inherit)
  • Thread.Builder uncaughtExceptionHandler(Thread.UncaughtExceptionHandler ueh)
  • Thread unstarted(Runnable task)
  • Thread start(Runnable task)
  • ThreadFactory factory()

とはいうものの、このThread.Builderインタフェースを直接使うことは、普通の開発ではほとんどないはずです。通常はSpringなどのフレームワークが使うもので、そのユーザーはスレッドがどのように作成されるかは意識しないで大丈夫なはずです。

 

Thread.Builder.ofPlatformクラス

Thread.Builderインタフェースの実装クラスで、従来のOSのスレッドに対応したJavaのスレッドを生成します。Virtual Threadに対して、従来のスレッドPlatform Threadと呼ぶようになっています。

Thread.Builderインタフェースで定義された以外のメソッドとして、以下の5種類のメソッドが定義されています。

  • Thread.Builder.OfPlatform group(ThreadGroup group)
  • Thread.Builder.OfPlatform daemon()
  • Thread.Builder.OfPlatform daemon(boolean on)
  • Thread.Builder.OfPlatform priority(int priority)
  • Thread.Builder.OfPlatform stackSize(long stackSize)

いづれも、従来のThreadクラスで定義されていた同等のコンストラクタもしくはメソッドがあります。

 

Thread.Builder.ofVirtualクラス

Thread.Builderインタフェースの実装クラスで、Virtual Threadに対応しています。ofVirtualクラスはThread.Builderインタフェースで定義されたメソッド以外のメソッドはありません。

 

Threadクラス

Virtual Threadに対応したため、いろいろとAPIが追加されたように勘違いするかもしれませんが、実際にはほとんど変化がありません。

  • static Thread.Builder.OfPlatform ofPlatform()
  • static Thread.Builder.OfVirtual ofVirtual()
  • static Thread startVirtualThread(Runnable task)
  • boolean isVirtual()

ofPlatformメソッドは前述したThread.Builder.ofPlatformクラスのオブジェクトを生成するメソッドです。同様にofVirtualはThread.Builder.ofVirtualオブジェクトを生成します。

ただし、これらのメソッドを使うことはほとんどないはずです。パラレル処理を行うためのフレームワークやライブラリを作成するのであれば使いますが、それ以外の場合はフレームワークがやるはずです。

というか、今でもnew Thread(() -> {...});のような直接スレッドを生成するようなコードを書いていたら、かなりやばいです。後述するExecutorServiceインタフェースを使うようにしましょう。

isVirtualメソッドだけは使用するかもしれませんが、Virtual Threadと分かったからといって、処理を変える必要はないはずなので、通常は使わないと思います。

 

java.base/java.lang.constantパッケージ

java.lang.constantパッケージはindyやcondyで使用するために必要なインタフェース/クラスを定義していますが、普通は使わないでしょうね。とりあえず、追加されたものだけ列挙しておきます。

 

ConstatntDescsクラス

定数が4種類追加されました。

  • DirectMethodHandleDesc BSM_CLASS_DATA
  • DirectMethodHandleDesc BSM_CLASS_DATA_AT
  • String CLASS_INIT_NAME
  • String INIT_NAME
  • MethodTypeDesc MTD_void

 

MethodTypeDescインタフェース

ファクトリメソッドが2種類追加されました。

  • MethodTypeDesc of(ClassDesc returnDesc)
  • MethodTypeDesc of(ClassDesc returnDesc, List<ClassDesc> paramDescs)

 

ModuleDescインタフェース

モジュール用のデスクプリターが追加されました。定義しているメソッドは以下の3種類です。

  • static ModuleDesc of(String name)
  • String name()
  • boolean equals(Object o)

 

PackageDescインタフェース

パッケージ用のデスクプリターが追加されました。定義しているメソッドは以下の5種類です。

  • static ModuleDesc of(String name)
  • static PackageDesc ofInternalName(String name)
  • String internalName()
  • String name()
  • boolean equals(Object o)

 

java.base/java.lang.invokeパッケージ

indy用のインタフェース/クラスなのでこのパッケージも使わないとは思いますが、メソッドのシグネチャが変更されているので、列挙だけしておきます。

MethodHandles.Lookupクラス

  • <T> Class<T> accessClass(Class<T> targetClass)
  • <T> Class<T> ensureInitialized(Class<T> targetClass)

いずれも<?>が<T>に変更になっています。

 

java.base/java.lang.constantパッケージ

これもいつものバージョンアップに伴う定数の追加です。

ClassFileFOrmatVersion列挙型

Java 21用の定数が追加されました。それにしても、今まで定数の説明がThe version recognized by ... だったのが、すべてThe version introduced by ...に変更されたのは何か意味があるのでしょうか???

  • ClassFileFormatVersion RELEASE_21

 

java.base/java.utilパッケージ

java.utilパッケージの変更は多いのですが、JEP 431 Sequenced Collectionsによるものがほとんどです。そこで、JEP 431に関するインタフェースから説明を加えていきます。

JEP 431ではコレクションに順序を取り入れ、先頭と末尾へアクセスするメソッドを定義します。また、順序を逆順にするメソッドも定義しています。

これらのメソッドを定義しているインタフェースは3種類あります。

  • interface SequencedCollection<E> extends Collection<E>
  • interface SequencedSet<E> extends Set<E>, SequencedCollection<E>
  • interface SequencedMap<K,V> extends Map<K,V>

インタフェースの継承関係を表したのが、下図です。


リストにはSequencedCollectionインタフェース、セットにはSequencedCollectionの派生インタフェースであるSequencedSetインタフェースが使われます。マップにはSequencedMapインタフェースです。

 

SequencedCollectionインタフェース

SequencedCollectionインタフェースはCollectionインタフェースの派生インタフェースで、以下の7種類のメソッドを定義しています。

  • SequencedCollection<E> reversed()
  • void addFirst(E e)
  • void addLast(E e)
  • E getFirst()
  • E getLast()
  • E removeFirst()
  • E removeLast()

メソッドの動作はメソッド名から分かると思います。

リストはもともと順序があるので、特に違和感なく使えるはずです。

jshell> var list = List.of(0, 1, 2, 3)
list ==> [0, 1, 2, 3]

jshell> list.reversed()
$2 ==> [3, 2, 1, 0]

jshell> list.getFirst()
$3 ==> 0

jshell> list.getLast()
$4 ==> 3

jshell> list.addFirst(-1)
|  例外java.lang.UnsupportedOperationException
|        at ImmutableCollections.uoe (ImmutableCollections.java:142)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:258)
|        at List.addFirst (List.java:796)
|        at (#5:1)
    
jshell>

reverseメソッドは逆順にしたリストを返すだけで、自分自身の順序は変更しません。

また、List.ofメソッドで作成されたリストはイミュータブルになるので、addFirst/addLast/removeFirst/removeLastメソッドをコールすると、上記のようにUnsupportedOperationException例外をスローします。

なお、reverse以外のメソッドはdefaultメソッドで実装されています。注意が必要なのは、addFirst/addLastメソッドのdefaultメソッドはUnsupportedOperationException例外をスローしていることです。このため、SequencedCollectionインタフェースの実装クラスの中にはaddFirst/addLastメソッドが使えないものがあります。

 

セット以外のインタフェースでは、Listインタフェース、Dequeインタフェース、BlockingDequeインタフェースがSequencedCollectionインタフェースの派生インタフェースになります。

なお、Queueインタフェースは両端にアクセスできないため、SequencedCollectionインタフェースの派生インタフェースとならないことに注意が必要です(実際にはQueueインタフェースのコンクリートクラスがSequencedCollectionインタフェースを実装していることも多いです)。

 

次にセットです。

セットは本来は順序はありませんが、SortedSetインタフェースおよびNavigableSetインタフェースの実装クラスだけは順序が存在します。また、その順序は実装クラスによって異なります。

SequencedSetインタフェースはSequencedCollectionインタフェースの派生インタフェースで、SortedSetインタフェースのスーパーインタフェースになります(NavigableSetインタフェースはSortedSetインタフェースの派生インタフェースです)。SequencedSetインタフェースはメソッドを1つだけ定義しています。

  • SequencedSet<E> reversed()

reversedメソッドの返り値の型がSequencedSetインタフェースになっただけですね。

SequencedSetインタフェースの派生インタフェースは前述したSortedSetインタフェースおよびNavigableSetインタフェースです。

これらのインタフェースの実装クラスにはTreeSetクラス、LinkedHashSetクラス、ConcurrentSkipListSetクラスがあります。LinkedHashSetクラスだけはSequencedSetインタフェースを直接実装しています。

なお、TreeSetクラスは前述したaddFirst/addLastメソッドのdefaultメソッドがそのまま使われています。つまり、addFirst/addLastメソッドを使用するとUnsupportedOperationException例外がスローされます。

 

最後がマップです。

マップもセットと同様に基本的には順序はありませんが、SortedMapインタフェースもしくはNavigableMapインタフェースの実装クラスは順序を持ちます。

SequencedMapインタフェースはSortedMapインタフェースのスーパーインタフェースになります(NavigableMapインタフェースはSortedMapインタフェースの派生インタフェースです)。

SequencedMapインタフェースが定義しているメソッドは以下の通り。

  • SequencedMap<K,V> reversed()
  • Map.Entry<K,V> firstEntry()
  • Map.Entry<K,V> lastEntry()
  • Map.Entry<K,V> pollFirstEntry()
  • Map.Entry<K,V> pollLastEntry()
  • V putFirst(K k, V v)
  • V putLast(K k, V v)
  • SequencedSet<K> sequencedKeySet()
  • SequencedCollection<V> sequencedValues()
  • SequencedSet<Map.Entry<K,V>> sequencedEntrySet()

SequencedMapインタフェースでは、アクセスする単位がキーと値がペアになったMap.Entryインタフェースとなります。SortedMapインタフェースがfirstKeyメソッドなどを定義しているのとは対照的です。

firstEntryメソッドとpollFirstEntryメソッドの違いは、firstEntryメソッドが単に最初のエントリーと取得するのに対し、pollFirstEntryメソッドは最初のエントリーを返して、そのエントリーをマップから削除するという点にあります。

lastEntryメソッドとpollLastEntryメソッドの違いも同じです。

jshell> var map = new TreeMap<String, String>(Map.of("a", "Alpha", "b", "Bravo", "c", "Charlie"))
map ==> {a=Alpha, b=Bravo, c=Charlie}

jshell> map.firstEntry()
$3 ==> a=Alpha

jshell> map
map ==> {a=Alpha, b=Bravo, c=Charlie}

jshell> map.pollFirstEntry()
$5 ==> a=Alpha

jshell> map
map ==> {b=Bravo, c=Charlie}
      
jshell>

SequencedMapインタフェースもreversedメソッド以外はdefaultメソッドで定義されています。SequencedMapインタフェースもSequencedCollectionインタフェースと同様にputFirst/putLastメソッドだけはUnsupportedOperationException例外をスローするようになっています。

SequencedMapインタフェースの実装クラスには、TreeMapクラス、LinkedHashMapクラス、ConcurrentSkipListMapクラスがあります。TreeMapクラスとConcurrentSkipListMapクラスはNavigableMapインタフェースを実装したクラスです。LinkedHashMapクラスだけはSequencedMapインタフェースを直接実装します。

なお、TreeSetクラスと同様にTreeMapメソッドもputFirst/putLastメソッドがdefaultメソッドのままになっています。このため、TreeMapクラスでputFirst/putLastメソッドを使用すると、UnsupportedOperationException例外をスローしてしまうことに注意が必要です。

 

Collectionsクラス

CollectionsクラスにはJEP 431関連のメソッドが4種類と、その他の1種類のメソッドが追加されました。

  • static void shuffle(List<?> list, RandomGenerator rnd)
  • static <E> SequencedSet<E> newSequencedSetFromMap(SequencedMap<E,Boolean> map)
  • static <T> SequencedCollection<T> unmodifiableSequencedCollection(SequencedCollection<? extends T> c)
  • static <T> SequencedSet<T> unmodifiableSequencedSet(SequencedSet<? extends T> s)
  • static <K,V> SequencedMap<K,V> unmodifiableSequencedMap(SequencedMap<? extends K,? extends V> m)

shuffleメソッドは、今まで引数がリストだけのオーバーロードと、リストとRandomクラスのオーバーロードが提供されていました。これに加えて、RandomGeneratorインタフェースのオーバーロードが追加されました。

これで、Randomクラス以外のSecureRandomクラスなども乱数として扱うことができるようになっています。

他の4種類のメソッドはSequencedXを生成するためのメソッドです。

unmodifiableSequencedXメソッドはSequencedXオブジェクトを変更不可にするためのメソッドで、今までのunmodifiableXメソッドと使い方は変わりません。

もう1つのnewSequencedSetFromMapメソッドはnewSetFromMapメソッドのSequencedSet版です。セットの実装にはマップが使われていますが、そのマップを指定してセットを作るメソッドです。あくまでも内部のマップを指定するためであって、マップからセットに変換するメソッドではないことに注意が必要です。

このため、引数のマップは空でなくてはいけません。

newSequencedSetFromMapメソッドも同じで、引数には空のSequencedMapオブジェクトを指定します。

 

Localeクラス

Localeクラスには2種類のメソッドが追加されました。

  • static Stream<Locale> availableLocales()
  • static String caseFoldLanguageTag(String languageTag)

availableLocalesメソッドは使用できるロケールの一覧をStreamオブジェクトで返すメソッドです。今までは配列が戻されるgetAvailableLocalesメソッドを使用していましたが、Stream APIを使用できるようになりました。

もう一方のcaseFoldLanguageTagメソッドは、IETF言語タグを比較する時などのためにCase Foldingするためのメソッドです。

たとえば、Scriptは先頭文字が大文字の略号が使用されるので、小文字で表記されていると大文字に変換されます。

jshell> var tag = "ja-kana-jp"
tag ==> "ja-kana-jp"

jshell> Locale.caseFoldLanguageTag(tag)
$2 ==> "ja-Kana-JP"
      
jshell>

variant以降のタグは大文字と小文字を区別しないため、小文字に統一されます。ただし、lvariantが使用されている場合はそれ以降のタグは変換されないままになります。

jshell> var tag1 = "ja-kana-jp-x-Java-Standard-Edition"
tag1 ==> "ja-kana-jp-x-Java-Standard-Edition"

jshell> Locale.caseFoldLanguageTag(tag1)
$2 ==> "ja-Kana-JP-x-java-standard-edition"

jshell> var tag2 = "ja-kana-jp-x-lvariant-Java-Standard-Edition"
tag2 ==> "ja-kana-jp-x-lvariant-Java-Standard-Edition"

jshell> Locale.caseFoldLanguageTag(tag2)
$4 ==> "ja-Kana-JP-x-lvariant-Java-Standard-Edition"
      
jshell>

 

java.base/java.util.concurrentパッケージ

java.util.concurrentパッケージの変更もJEP 431 Sequenced Collectionsによるものがほとんどです。これらは省略して、Virtual Threadに関連した変更を紹介します。

 

Executorsクラス

Virtual Threadに関するメソッドが2種類追加されました。

  • static ExecutorService newVirtualThreadPerTaskExecutor()
  • static ExecutorService newThreadPerTaskExecutor(ThreadFactory threadFactory)

スレッドを使いまわすスレッドプールには応答速度重視型とスループット重視型の2種類があります。一般的には、計算処理がメインであれば応答速度を重視し、Webシステムであればスループットを重視します。

スループットを重視した場合、タスクごとにスレッドを割り当てるThread per Task(もしくはThread per Request)のスレッドプールが用いられてきました。

しかし、従来のスレッドであればスレッド生成が重い処理であり、メモリも大量に使用してしまいます。そこで、導入されたのがVirtual Threadです。

Virtual Threadは従来のPlatform Thread上で動作しますが、ユーザーからは通常のスレッドと同じように動作します。

newVirtualPerTaskExecutorメソッドは、Virtual Threadに対応したThread per Taskタイプのスレッドプールを生成します。

もう一方のnewThreadPerTaskExecutorメソッドは引数にThreadFactoryオブジェクトを指定します。Virtual Threadに対応したThreadFactoryオブジェクトであればVirtual Threadを使用しますが、それ以外では従来のPlatform Threadになります。

 

java.base/java.util.regexパッケージ

正規表現を表すPatternクラスにメソッドが追加されました。

 

Patternクラス

Stringクラスで追加されたメソッドの大本のメソッドが追加されました。

  • String[] splitWithDelimiters(CharSequence input, int limit)

StringクラスのsplitWithDelimitersメソッドは内部で、PatternクラスのsplitWithDelimitersメソッドをコールしています。

 

また、APIの変更ではありませんが、正規表現で絵文字のプロパティが使えるようになりました。追加されたプロパティは以下の6種類です。

  • Emoji
  • Emoji_Presentation
  • Emoji_Modifier
  • Emoji_Modifier_Base
  • Emoji_Component
  • Extended_Pictographic

これらのプロパティは\p{IsX}の形式で使用することができます(Xがプロパティ名)。

jshell> Pattern.compile("\\p{IsEmoji}").matcher("😊").matches()
$1 ==> true
    
jshell>

 

java.net.http/java.net.httpパッケージ

java.net.httpモジュールはHTTP Client APIを提供しています。その中のHttpClientクラスに変更がありました。

 

HttpClientクラス

HttpClientクラスは今まで明示的にクローズすることをしませんでした。これに対し、Java 21ではAutoClosableになり、クローズを行えるようになります。また、これに伴い5種類のメソッドが追加されました。

  • void close()
  • void shutdown()
  • void shutdownNow()
  • boolean awaitTermination(Duration duration)
  • boolean isTerminated()

HttpClientクラスがAutoClosableインタフェースを実装するようになったため、closeメソッドが追加されています。

shutdownメソッドも通信をクローズしますが、sendメソッドやsendAsyncメソッドが完了するまで待ちます。これに対し、shutdownNowメソッドは完了を待たずにクローズします。

また、awaitTerminationメソッドは指定した時間までは、送受信の完了を待ちます。タイムアウトしてしまった場合はfalseを返します。

closeメソッドは基本的にはshutdownメソッドをコールしますが、完了しない場合awaitTerminationメソッドを1日のタイムアウトでコールします。awaitTerminationメソッドでInterruptedException例外がスローされた場合、shutdownNowメソッドをコールしているようです。

最後のisTerminatedメソッドは送受信が完了しているかどうかを調べるメソッドです。

 

 

といいうことで、Java 21のAPIの変更について紹介しました。APIの変更という観点からすると、JEP 431の変更が大きかったですね。とはいうものの、リスト以外で先頭や末尾にアクセスする場面というのは、ほとんどないような気がしますが...

また、JEP 444 Virtual Threadへの対応ですが、こちらはAPIの変更としては少ないです。逆にいうと、従来のPlatform Threadと同じように使えるということでもあります。

それ以外の変更は意外に少ないです。個人的にはHTTP ClientのAutoClosable対応がうれしいところですね。

 

さて、次のJava 22ではFFM APIが入るのかどうか?それによって、APIの変更度合いも違ってくるはずです。

2023/09/12

Who's Who in Java 現代編

このエントリーをはてなブックマークに追加
_DSC0729

 Who's Who in Javaの続きです。

前回はJavaを作っていた人たちを紹介しました。本エントリーでは現在、Javaを作っている人たちを紹介します。

発表資料でいうと、ここからです。

本エントリーで紹介する人は、今のところすべてOracleの社員です。オープンソースになったとはいっても、Javaの方向性を決めて、実装しているのは、やはりOracleの人が中心です。


Mark Reinhold

まずはじめに紹介するのが、JavaのチーフアーキテクトであるMark Reinholdです。

Markが表舞台に登場したのは、J2SE 1.4で導入されたNIOです。

J2SE 1.4のころの大きめの標準APIは、JCPで標準策定が行われていました。NIOはJSR 51です。JSRはJava Specification Requestの略です。

そのJSR 51のスペックリードがMarkでした。

NIOも結構もめたらしいのですが、それをまとめたのがMarkだったということをJSR 51のエキスパートグループにいらした方から聞いた覚えがあります。JSR 51のエキスパートグループを見てみれば分かりますが、日本の某企業も加わっているのが分かりますね。

その後、MarkはJava 5のスペックリードになります (JSR 176)。彼は技術力だけでなく、交渉をまとめる調整力があったからだと思います。

Java 6ではMarkはスペックリードを外れます。Java 6からJava 7のころは、SunがOracleに買収されたり、オープンソース化や、関数型の導入などでゆれにゆれていた時期です。

そこで、Java 6のスペックリードがまとめきれなくなったのか、途中からMarkが再登板します。

Java 7のリリース予定が遅れまくっていた時に、ラムダ式はJava 8にスリップさせることを決めたのもMarkです。

Javaを作っている開発者や、JCPのエキスパートグループなどから全幅の信頼を持たれていたMarkだからこそ、まとめられたのだと思います。

このころ、SunでJavaを作っていた日本人開発者の方から聞いた話なのですが、「Markが言うことなら信用できる」と多くの開発者が言っていたらしいです。

そして、激動期のJavaのスペックリードをJava 9までつとめます。Java 10からはこの後に紹介するBrian Goetzがスペックリードとなりました。

現在では大きな方針変更のたびにMarkが引っ張り出されています。たとえば、LTSの期間を変えるとか、JVMLSのエントリーで紹介したProject Leydenなどです。


彼がスペックリードだった時代、JavaOneのテクニカルキーノートといえばMarkでした。

"Welcome to JavaOne"で始めるのが恒例で、彼の口癖にa lot ofではなくa bunch ofがあります。こういう言い方を知ったのも彼のセッションでしたね。

しかし、彼はSunもしくはOracleが主催のイベント以外では登壇をほとんどしていません。たぶん、Devoxxぐらいじゃないかなぁ。

日本でJavaOneをする時に、Markに来日してもらおうと、当時Oracleだった寺田さんが奮闘していたのですが、結局果たされず。ぜひ、一度は日本にも来てほしいですね。


Brian Goetz

Mark ReinholdからJavaのスペックリードを受け継いだのがBrian Goetzです。肩書としてはJava Language Architectです。

Brianはもともと自分の会社を持っていました。その当時、IBMのDeveloperWorksという技術コミュニティサイトがあって(今はIBM Developerになっています)、そこに多くの記事を書いていました。DeveloperWorksは日本語サイトもあって、Brianの記事も訳されていて、さくらばも読んでました。残念なことにDeveloperに衣替えした時に、日本語のサイトはなくなってしまったようです。

また、彼はJSR 166 Concurrency Utilitiesのエキスパートグループのメンバーでもありました。JSR 166がJ2SE 5に導入された後、Brianが中心になってJava Concurrency in Practice (日本版はJava並行処理プログラミング)を書き上げています。

もう20年近く前の本ですが、今でもJavaでパラレル処理について一番おススメできる書籍です。残念ながら、日本語版は絶版になってしまいましたが...

さて、この本が出版されたころに、BrianはSunに入ります。

彼が担当したのが、Project Lambdaです。

Project Lambdaはほんといろいろあったプロジェクトです。

関数型をJavaに導入するということで、Project Lambdaの前に前哨戦があり、いくつもの提案がされていますし、もちろん反対派も多かったのです。

たとえば、前のエントリーで紹介したJoshua BlochとNeal Gafterはそれぞれ別の方式を支持し、そのせいで仲たがいしてしまったという噂もあります。

Project Lambdaになってからも、二転三転してやっとまとまったのがJava 8だったわけです。

Brainはプロジェクトリードとして、Project Lambdaをまとめたわけです。

その後も、Project AmberやProject Valhallaのプロジェクトリードになり、Java 10からはJavaのスペックリードになりました。

これからのJavaの方向性を決めているのが彼だと言い切っても間違いではないです。

BrianはOpenJDKでも、そのつどつどでドキュメントを書いていますし、InfoQなどにも記事を書いています。それだけでなく、メーリングリストでもたびたび投稿を行っており、他の開発者からの質問にも丁寧に答えています。

すごい忙しい人だと思うのですが、よくこれだけやるなぁと本当に頭が下がります。


John Rose

Brian GoetzがJava言語の人だとしたら、JVMの人といえばJohn Roseです。

John RoseはJavaOneのキーノートへの登壇こそないものの、JVMのセッションでおなじみです。

さくらばがJohnのことを知ったのは、JSR 292 Supporting Dynamically Typed Languages on the Java Platformのスペックリードとしてです。

JSR 292は新しいバイトコードであるinvokeDynamic、いわゆるindyを導入したプロジェクトです。indyはJVM上で動的型付け言語の実装を行いやすいように、実行時に実行するメソッドを動的に決定することのできるバイトコードです。

また、これに伴いDa Vinci Machine Project (Multi-Language VM)のプロジェクトリードにもなっています。

そして、これがJVMLSにつながるわけです。

現在はProject Panamaのプロジェクトリードにもなっています。


スペックリードたち

ほんとにJavaを作っている人たちをあげていくとキリがないのですが、その中から今活躍している4人を紹介します。


左上のPaul SandozはJVMからJavaの言語仕様まで広く活躍しています。

今のメインはProject PanamaのVector APIですね。

Project Panamaは大別して、2つのサブプロジェクトがあって、1つがPaulが主導しているVector API、他方が次に紹介するMaurizioが主導するForeign Function & Memory API (FFM)です。

JavaOneでも彼のセッションはおなじみで、柔らかい口調で、楽しくてしょうがない感じで話すのが印象的です。


左下のMaurizio Cimadamoreは前述したFFMを主導しています。

もともとコンパイラが得意で、javacにおけるラムダ式の部分はほとんど彼が書いたらしいです。これはOpenJDKのコミッターである @bitter_fox さんに聞いたので、たしかなはず。

他の開発者はMarkとかBrianというようにファーストネームで呼んでますけど、@bitter_foxさんがMaurizioさんといつも呼ぶので、なんとなくMaurizioさんと私もさんづけで呼ぶようになってしまいましたw


右上のRon PresslerはVirtual Threadを策定したProject Loomのプロジェクトリードです。

リードをするのはLoomがはじめてのはず。というか、それ以前に彼が何をやっていたのかさくらばはよく知らないのです。

Project Loomはもうそろそろ終わりが見えてきたので、次にRonが何をはじめるのか楽しみです。


ここまでの3人はどちらかというとJVM側の開発者でしたが、ライブラリを作っている人もいます。右下のStuart Marksもその1人。

彼もProject Lambdaなどのプロジェクトにも参画していましたが、今はコアライブラリチームの活動が主体のようです。特にコレクションフレームワークですね。

むきむきJavaでイシダさんがSequenced Collectionsについてプレゼンしてくれたのですが、そのSequenced CollectionsのJEPを書いたのも、プルリクしたのもStuartでした。

ところで、上の写真でStuartが白衣に聴診器をつけてます。これは、2016年のJavaOneのコミュニティキーノートでSteven Chinの企画で寸劇をしたのですが、その時にDr. Deprecatorという役でStuartが演じたものでした。

彼はこれが気に入ってしまったようで、毎年Dr. DeprecatorとしてJavaOneに登場してます。


Javaコミュニティ

ここで紹介する3人は、マネージメント側の人たち。特にJavaコミュニティに関わる人たちです。

3人とも同じTシャツを着ているのは、2022年のJavaOneのキーノートセッションで撮ったからです。


一番左側のGeorges SaabはJava Platform Groupの上級副社長です。そして、JavaOneのキーノートといえばGeorgesです。

Georgesは元々は開発者でJavaのGUIであるAWTを作っていました。

その後、BEAに転職して、そのBEAがOracleに買収されて、Oracleに戻ってきました。Oracleに戻ってきた時にはBEAのJRockit担当の副社長だったのですが、今ではJava全般を担当しています。


真ん中のChad Arimuraも副社長で、Javaのデベロッパーリレーション担当です。Java Championの事務局も彼に担当していただいてます。

彼も元々開発者で、サーバーレスのFn Projectなどを作っていました。

Arimuraという名字でお分かりのように日系の方なのですが、日本語は全然喋れないです。

そういえば、2019年に東京で開催されたOracle Codeで @bitter_fox さんと私でVector APIとVirtual Thread (当時はFiber)のデモをキーノートセッションで行いました。この無茶ぶりをしてきたのが、Chadですww


右側のSharat Chanderは肩書はプロダクトマネージャーですが、Sunの頃からJavaOneなどのイベントの取りまとめなどJavaコミュニティに関する業務を一手に引き受けている感じです。

2015年からはJavaOne (or Code One)のMCも彼が担当してますね。

X (元Twitter)でも、Javaに関するツィートをいっぱいしてます(それ以外のツィートも多いですけどw)。


Duke

最後に忘れてはならないのが、Dukeです!

言語でマスコットを使ったのはJavaのDukeがはじめてだと思います(さくらばが他を知らないだけかもしれませんが...)

前回のJames Goslingの説明で、Javaは元々情報家電向けのOakという言語だったことを書きました。このOak時代に、プロトタイプとしてStar 7というタブレットの分厚いののようなマシンを作成していました。

下の写真はComputer History Museumで展示されていた、Star 7 (* 7)です。

_DSC5804

このStar 7で、動いていたのがDukeです!この時から側転してましたww

つまり、Dukeの方がJavaよりも古くから存在するわけです。DukeのデザインをしたのがJoe Parlang。彼はのちにシュレックなどにも参画しています。

この当時は、Dukeには特に名前はなく、その形状からFang (牙)と呼ばれていました。しかし、当時のマーケの人が、「Fangなんてかわいそうな名前ではなくて、Dukeにしましょう!」と言ったとか言わないとか...

JDK 1.0のアルファ版からサンプルとしてDukeが側転するアプレットが含まれていたので、Javaを触る人は誰もがDukeを目にしていたわけです。

時代が変わって、JavaがOpenJDKでオープンソース化された時、Dukeもオープンソース化されました。JavaのライセンスはGPL Classpath Exceptionですが、DukeはBSDライセンスです。したがって、改変することも自由、商用利用も可能です。

ちなみに、Dukeはコミックにもなっていて、JavaOneで配布していました。そのコミックは The Amazing Adventures of Duke で読めます。


むきむきJavaではDukeを使ったものとして、下の4つの写真を紹介しました。

まずはやっぱりぬいぐるみ。

さくらばも各種Dukeのぬいぐるみ持ってます。ハンドパペットも持っていたりしてw

左下のDukeおにぎりはもちろん日本のものです。最古のDukeおにぎりは日本ではじめて横浜で開催されたJavaOneの時だと記憶しているのですが、もしかしたら違うかもしれません。

この時の企画は、当時SunのIさんでしたね。

その後、日本のJavaのイベントではDukeおにぎりはおなじみになってます。上の写真のDukeおにぎりは造形がイマイチですけどw

右上のギターのような楽器はウクレレです。Dukeleleといいます。

これも日本の企画でした。

Java 10周年の年である2005年に東京でJava Computing 2005 Springというイベントが開催されました。この時に、前述のIさんが記念になるノベルティを企画していたのです。

その当時、Javaで書かれた3DのウィンドウシステムであるProject Looking Glass (LG3D)が話題になっていました。

作者の川原さんはウクレレが好きで、登壇する時もウクレレを持ちながら登壇していました。また、LG3Dのコミュニティにやはりウクレレが好きなKさんが、三角形のFlukeというウクレレを見つけてきて、これだったらDukeになるんじゃないかとIさんに提案したのです。

そこからとんとん拍子に話が進んでDukeleleが誕生したわけです。

私がサムネイルに使っている写真で手に抱えているのがDukeleleです。

DukeleleはアメリカのJavaOneでも販売されたのですが、2005年と2006年だけ。持っている人はかなりレアですよ。

右下のずんぐりしたDukeは、Javaの20周年のパーティーを東京で行った時のDukeケーキです。このためにだけ、寺田さんが特注オーダーで作ってもらったものです。

この形にするために、かなりずっしりとしたケーキで、外側はマジパンで成形されてます。ちゃんと食べられるんですよ、このケーキw

これ以外にもいろいろなノベルティなどにDukeは使われていますね。


最後のDuke's Choice Awardというのは、毎年JavaOneでその年にJavaで作られた製品やサービスを表彰するというものです。

日本からもDuke's Choice Awardを受賞しています。たとえば、古くはNTTドコモのi-Modeなんてのも受賞していました。さくらばの友人だと、九州大学(当時は九州工業大学)の小出先生(2005年)や、サムライズムの山本ユースケさん(2019年)が受賞しています。

Duke's Choice Award _DSC3612


この他にも、AlanやAlex, Joe, Michael, Charlie、佐藤さんと、あげていけばキリがありません。そうそう、日本でJDKを作っているDavidも!

普段はJavaを作っている人たちはあまり表には出てきませんが、このエントリーで少しでも親しみを持っていただければと思います。


むきむきJava ふりかえり

最後にちょっとだけむきむきJavaの感想など。

ほぼはじめてだと思われる3人のプレゼンを聞いたのですが、はじめてだとしたら、まぁよかったのではないでしょうか。

JJUGのLT大会でShiryuさんが伝えることが多すぎて失敗したと嘆いていましたし、司会の cero_t さんからはメッセージは1つに絞った方がいいよとアドバイスもらっていたので、それ以外の視点で1つだけコメントしておきます。


Shiryuさんと、Kageiさん、イシダさんの3人のうち、一番わかりやすいと感じたのはイシダさんのSequenced Collectionsの話でした。

では、イシダさんと他の2人はどこに違いがあったのでしょう。

それは、ShiryuさんとKageiさんは自分が分かっていることを知らない人に説明したのに対し、イシダさんは自分の知らないことを調べてそれを知らない人に説明したという点です。

これはベテランの人でもやりがちなのですが、自分が分かっている分野だと、無意識のうちにその分野の言葉を使ってしまうのです。

もちろん、聞いている方はその分野は知らない世界なので、言葉も分かりません。そのためにプレゼンの理解が妨げられてしまうわけです。

プレゼンのターゲットが異なれば、言葉も変えていかなくてはならないのですが、普段、普通に使っている言葉だと、その言葉が相手に通じるかどうかすら考えなくなってしまうのです。

専門用語であれば「これは通じるかな?」と考えるかもしれないですけど、意識せずに使っているその世界の言葉はなかなか気づきにくいです。

以前、知人と雑談していた時に、家電の設定の初期値のことをデフォルトと言った時にまったく通じなかったことがあります。デフォルトってプログラムを書いている人であれば当たり前のように使っている言葉ですけど、この業界以外では通じない言葉です。

しかも、その知人は保険屋さんだったので、デフォルトがまったく違う意味で使われており、家電に対して使うという意味が分からなかったらしいです。金融系であれば、デフォルトは債務不履行のことなので、私たちが使う意味とは全然違いますよね。


これに対し、イシダさんは自分が知らないことを調べてプレゼンしたので、知らない世界の言葉は使わずに (というか使えなかったのだとは思いますが)、自分の言葉で説明しようとしていました。

ここが聞く側の分かりやすさの違いになっていたと思います。

プレゼンするときは、ターゲットによって言葉を変える。そして、説明する言葉が相手に理解できるかどうかを考えるというのが重要になってきます。

この点に気をつければ、次のプレゼンはもっとよくなると思いますよ。

2023/09/10

Who's Who in Java 過去編

このエントリーをはてなブックマークに追加
James Gosling, Community Keynote, JavaOne 2015 San Francisco

むきむきJava という若手中心のJavaのコミュニティが立ち上がり、第1回目のイベントをやるというので、ぜんぜん若手ではないのですが、プレゼンさせてもらいました。

コミュニティの趣旨であるJava筋をむきむきにするようなのは若者にまかせて、Javaの初期から関わっているおじさんとして技術ではない部分で興味を持ってもらおうという内容にしました。

題して、Who's Who in Java です。発表資料はこちら。

Who's Whoというのは日本語で言うと紳士録とか名士録というものです。最近だと使わない言葉ですね。

ようするに、Javaで有名な人を紹介するということです。というか、Javaを作ってきた/作っている人を紹介するプレゼンをしました。

話しだすと止まらないぐらいエピソードがいっぱいあって、時間を盛大にオーバーしてしまってすみませんでした。

できれば、1人ぐらいは覚えておいてほしいですね。

せっかくなので、ここで紹介しましょう。まずは作っていた人たちから。


James Gosling

1人目は "Javaの父" ことJames Goslingです。

彼はカーネギーメロン大学在籍中にEmacsを作った人として有名ですけど、結局Gosling EmacsはGNU Emacsにとってかわられてしまいました。

また、Sun Microsystemsに入社した後もSunOS向けのウィンドウシステムであるNeWSを作成したりしています。NeWSはDisplay PostScriptとは違いますが、PostScriptを使って描画するというかなり画期的ウィンドウシステムだったのですが、結局はX Windowにとってかわられてしまいました。(昔、SonyのワークステーションがNEWSで、NeWSとよくゴッチャになりやすいというのもありましたw)

3度目の正直ではないですけど、彼が情報家電向きに作った言語がOakです。

でも、結局情報家電向けには受け入れられず、方向性を変えてJavaとなったわけです。

彼は常にTシャツにジーンズといういでたち。

上の写真は2015年のJavaOneのコミュニティキーノートでのGoslingです。この時もTシャツ、ジーンズでしたが、ほんとにいつでもTシャツ、ジーンズです。

Sun Microsystemsだったころには、JavaOnのドレスコードの記載があって正装がTシャツとジーンズと書かれていたぐらいです。こういう遊び心はなかなか見かけなくなってしまいましたね。

そして、JavaOneでは毎年新しいTシャツを作っていて、それをキーノートの最後に投げるというT Shirt Tossも恒例になっていました。

2004年や2005年のJavaOneではT Shirt Toss Machineのコンテストがあったりしました。2005年は確か下の写真のマシンが優勝したような気がするのですが、詳細は覚えてないです... 

JavaOne 2005 San Francisco

James GoslingはOracleをやめた後、ベンチャーにいったりしてましたが、現在はAWSに所属しています。

そして、2019年にはマウンテンビューにあるComputer History Museumで殿堂入りしました。

たまたま、この年にComputer History Muesumに行ったら、ミュージアムのロビーにこの年に殿堂入りした4人が大きく取り上げられていてビックリしましたw

ちなみに、さくらばはJamesが来日した時に日本のSunの人に誘っていただいて、ランチを一緒に食べに行ったことがあります。

その時に、「Java言語仕様」を持って行って、サインしてもらったのもいい思い出です。

下の写真がサインをしてもらっている時に撮ったものです。

James Gosling, JJUG Cross Community Conference


Bill Joy

次はBill Joyです。

Bill JoyはあまりJavaのイメージはなくて、BSDのイメージの方が強いとは思いますが、初期のJavaの強力な推進者でもありました。

ちなみに、むきむきJavaの参加していた人たちはLinuxがUnixだと思っていたぐらいなので、BSDと言っても「はぁ?」という感じなんでしょうね。


Javaがリリースされたころ、すでにBill Joyは伝説のプログラマでした。

Bill JoyはBSDのcshやviを作った人で、TCP/IPのスタックを作ったのも彼でした。週末に1人でBSDのカーネルを書き換えたという伝説もあったりします。

で、そのBill Joyですが、OakのころからJavaに関与しています。Java言語仕様の作者としてもGoslingの次にクレジットされています。

ただし、彼がJVMを作っていたというわけではないです。

Javaが発表された1995年に、日本のJavaのお披露目的なイベントがたしかニューオータニでやったのですが、そこでプレゼンしたのがBill Joyでした。

その時に、Javaのカップをもらって、いまだに手元にあります。

その後、JavaのJiniやJXTAを進めていたのですが、これらはイマイチでしたね。どちらも分散オブジェクトシステムだったのですが、今となって考えるとオブジェクトを分散させて使う意味はほとんどなかったですね。

そういえば、JavaOneの前日にチュートリアルのJava Universityというイベントがあったのですが、そこでさくらばがJiniのコースを受けたことがあります。

コースの最後になって、なんとBill Joyがやってきたのです。抽選でJiniの本をくれるということになったのですが、そこで、あててしまったのですよ。

で、その場でJiniの本にBill Joyにサインしてもらいました!!

ちなみに、上の写真は2005年のJavaOneで撮ったのですが、このすぐ後にSunを退職されてしまいました。今はベンチャーキャピタルのパートナーになっています。

また、彼もComputer History Museumの殿堂入りしています。


Joshua Bloch

Joshua Blochといえば、Effective Javaの著者として有名ですね。Javaを使っている開発者であれば、ぜひ読んでほしい本です。

そのJoshua Blochですが、コレクションフレームワークなどを作っていた人でもあります。今でもJavaのソースコードを読んでいると、Joshua Blochがクレジットされているコードがいっぱいあります。

さて、彼はプレゼンの名手でもあります。Effective JavaもJavaOneのセッションとしても有名でした。

そして、当時の同僚であるNeal Gafterと一緒にJava Puzzlersというセッションも担当していました。

このJava Puzzlersは、簡単にいうとJavaのクイズです。言語仕様やAPIの分かりにくいところをクイズにして、答えてもらうセッションです。しかし、単なるクイズではなく、どうすればその間違いを防ぐことができるか、そして最後には教訓まで含めるという、とても教育的なセッションでした。

たとえば、こんな問題です。オリジナルはDateクラスを使っていたのですが、Date & Time APIに書きかえてあります。

このクイズの答えは2です。

なぜかというと、staticであるクラス変数は上から初期化されます。

つまり、INSTANCEの方がCURRENT_YEARより先に初期化されます。

INSTANCEの初期化でElvisのコンストラクタがコールされますが、コンストラクタ内のCURRENT_YEARはまだ初期化されていません。そのため、CURRENT_YEARは0のままになっています。

そのために、beltSizeは-1930になってしまうわけです。

この問題の教訓はクラス変数の初期化に他のクラス変数は使わないようにすることと、初期化の順番に依存してしまうようなコードは書かないようにしましょうということです。

このクイズのタイトルであるElvis LivesのElvisは、もちろんElvis Presleyのことです。晩年のElvisはどんどん太ってしまっていたのですが、そのElvisが生きていたらウェストがどのくらいになっていただろうねというジョークになっているわけです。

この問題に限らず、Joshuaのパズルはウィットに富んでいます。

彼らはJava Puzzlersのセッションには、おそろいのつなぎを着て、セッションの開始する時に"We are Click and Hack, The Type-it Brothers!"と言ってはじめるのです。

これも元ネタがあって、アメリカのラジオ番組の「Car Talk」のパズルコーナーから来ているらしいです。オリジナルは"Click and Clack, the Tappet Brothers"なんだそうです。

Java Puzzlersも書籍になっていて(日本語の翻訳はすでに絶版なのですが...)、その日本語版には訳者の柴田さんが、クイズの元ネタや英語ならではのジョークの解説を書いてくれています。こういうジョークを思いつくJoshuaもすごいですけど、柴田さんも裏をとるのが大変だったでしょうね。

ちなみに、彼はSunを退社した後、Googleにいましたが、現在はカーネギーメロン大学の教授をしています。


Scott McNealy, John Gage

過去の人の最後はScott McNealyとJohn Gageです。

彼らはJavaを作っていたわけではないのですが、Javaにとってとても重要な人たちです。

Scott McNealyは、Javaがリリースした当時のSun MicrosystemsのCEOです。

英語でべらんめえ調というのも変な感じですけど、ほんとそんな感じで話す人でした。上の写真でも彼は手にカードを持っていますが、あれはカンペです。

プレゼンでカンペ持って喋ってもいいと教えてくれたのが(もちろん、直接教えてもらったわけではないですけどw)彼でした。でも、カンペを見ながら話すことはないですね。

Scott's Top 10というのは、彼のジョークのことです。JavaOneなどのキーノートで10個のジョークを言っていくわけです。カンペに1つずつジョークが書いてあって、受けたらそれをとっておいて、受けなかったら捨ててしまうという。

変なCEOですよね。


そして、John Gageです。

彼のSunでの肩書はScientistでした。Sunのスローガンに"The Network is The Computer"というのがあります。このフレーズを考え出したのが、John Gageでした。

現代ではネットがなければ、ほんとに何もできないので、このフレーズも納得なのですが、ネットワークの普及期にこれを提唱するというのはほんとに先見性があったのだと思います。

さて、彼は長らくJavaOneのMCでありました。彼がいなければ、当時JavaOneがあれだけ盛り上がらなかったと思います。

彼が必ずJavaOneで言うフレーズに"Don't be Shy!"というのがあります。知らない人たちの集まりではあるけども、Javaという共通の話題があるのだから恥ずかしがらずに話しましょうということです。

彼のMCにおけるポスチャーはさくらばのお手本でした。ポスチャーに関しては彼から学んだことがほんと多いですね。


つらつらと書いていたら、やっぱり長くなってしまいました。

ほんとはTim LindholmやGraham Hamilton、2020年に亡くなってしまったBill Shannon、Roberto Chinninci、Chet Haase、そして奥津さんなど、取り上げたい人はいっぱいいるのですが、このエントリーではこのへんでやめておきます。

そして、今Javaを作っている人たちは次のエントリーで!

2023/09/07

JVM Language Summit 2023 その2

このエントリーをはてなブックマークに追加

JVMLSの続き。

前のエントリーでは行き方や、宿泊などについて書きましたので、本エントリーではJVMLSの本編について紹介します。


JVMLSは3日間行われますが、最終日は午前だけなので、実質2.5日です。

また、基本的にはシングルトラックで、Workshopという名のQ&Aセッションだけは2つのトラックに分かれます。

タイムテーブルはこちら


LTでも話したのですが、全体的な感想は

上に書いてあるProject Panamaは主にForeign Function & Memory (FFM)の方です。Vector APIの方はだいたいできているので。

2番目の起動時間は2019年の時にも話題にはなっていましたが、Project Leydenが立ち上がったことで、本腰を入れた感じですね。

3番目ですが、今年はProject Amberのセッションがありませんでした。Pattern Matchingでまだ残っているものもありますが、DOPに関する機能に関しては終わりが見えてきた感じがあります。

そこで、Brian Goetzが新しいことを始める予感が...

Project Valhallaは最終日にセッションがありましたが、まだまだ決めなくてはいけないことが多そうな感じです。

それにしても、みんな年取りましたね。それでも、みなさん元気な様子でよかったです。


セッションはYouTubeで公開しているので、興味があるものがあればぜひ見てみてください。


さて、セッションの中で櫻庭が気になったセッションを簡単に紹介します。


A Classfile API for the JDK

Brian Goetzのセッションで、Classfile APIというのははじめて聞きました。

Classfile APIというのは、簡単に言えばクラスファイルやバイトコードをいじるためのAPIです。

JDKの内部ではクラスファイルを扱うためにASMが使われていました。しかし、ASMはOpenJDKの外部で作られているライブラリで、最新のクラスファイルに対応するまでには時間がかかってしまいます。

OpenJDKでは最近でもクラスファイルのアトリビュートが追加されたり、定数を扱うためのCondyが登場したり、さらにValhallaなどでバイトコードが追加されるかもしれません。

そこで、標準でクラスファイルやバイトコードを扱うためのAPIを作りましょうというのがBrianのセッションです。

すでにプロトタイプはあるようで、コード例も紹介されていました。


Continuations - Under the Covers

Continuationは日本語では継続です。

Virtual Threadでは頻繁にスレッドの切り替え(コンテキストスイッチ)が行われます。これを従来のスレッドのコンテキストスイッチで行っていたら、メモリも食うし、時間もかかるでよいことはありません。

そこで、Virtual Threadでは継続(実際には限定継続)を使用して、処理の中断、復帰を高速に行っています。

この継続のコードはほとんどがJavaで書かれています。処理の中断、復帰にはJVMスタックを退避したり、戻したりする必要があるのですが、それをJavaで書いてあるわけです。しかも、JVMスタックのすべてを退避させるのではなく、部分的な退避、復帰で済ませるような工夫もされています。

このセッションではその限定継続のアルゴリズムについての解説を行っています。


Project Leyden

Project LeydenはGraalVMのネイティブイメージを作成するAOTコンパイラを、OpenJDKに正式に導入しようというプロジェクトです。

GraalVMのAOTを持ってくるだけなんじゃないかと思ったら、やっぱりいろいろと考えなくてはいけないことがあるというのが、このセッションです。

スピーカーはなんとMark ReinholdとJohn Roseの二大巨頭!!


Value Objects in Valhalla

Project ValhallaはJavaの型システムを考え直すというプロジェクトです。

歴史的経緯もあって、Javaはプリミティブ型と参照型という2つの型があるわけですが、その中間に位置するのが本セッションのValue Objectです。

とはいっても、やっぱり簡単には導入できなくて、なかなか進んでいない感じがしますし、まだまだ時間がかかるかなぁという感じもします。

Value Objectってどういう時に使えばいいか個人的にはよく分からないんですよね。型が増えると、考えなくてはならないことも増えそうです。

それでも、現状がどうなっているのかを知るにはいい機会になりました。


他にもおもしろいセッションがいろいろあるので、JVMが好きな人はぜひセッション動画を見てみてください。

そして、来年、一緒にJVMLSに参加しましょう!

2023/09/04

JVM Language Summit 2023 その1

このエントリーをはてなブックマークに追加

4年ぶりに開催されたJVM Language Summit (JVMLS)に参加してきました。

上の資料は8月31日に開催されたJJUGナイトセミナーの夏のLT大会でプレゼンした時の資料です。5分しかないLTなので、このエントリーで補足していきます。

JVM Language Summitとは

JVMLSは2008年から開催されたカンファレンスで、今年は4年ぶり13回目の開催になります。

2008年というとJVM上で動作する言語がいろいろでてきて、JVMでも動的型づけ言語をサポートするバイトコードを導入するかどうか議論をしていたころです。ちなみに、このバイトコードはinvokeDynamic (通称 indy)となり、Java 7から使えるようになりました。

そんな時に開催されたのが1回目のJVMLSです。

タイムテーブルを見ると、JRubyやScala、GroovyなどのJVM言語のセッションが並んでいることが分かります。

つまり、当時のJVMLSはJVM言語の人たちが一堂に会したカンファレンスでした。これがSummitになっている理由です。

しかし、だんだんとJVM言語のセッションは減っていき、その代わりにJVMとJavaの言語仕様などのセッションが増えてきました。今ではSummitは名前だけで、最新のJavaとJVMのカンファレンスになっています。

なお、今でもJVM言語関連でセッションを持つのはJRubyのCharles Nutterと、Graalの人たちぐらいになってしまいました。今年もCharlesはJRubyのセッションをするはずだったのですが、急用があったということでキャンセルになってしまいました。残念。

JVMLSの会期は3日間。その後にOpenJDKのコミッターによるアンカンファレンスのOpenJDK Committers' Workshopがあります。このワークショップは表向きはコミッターに限定しているようですが、実際にはコミッターでなくても参加できます。


櫻庭は2018年、2019年に引き続き、今回 3回目のJVMLSです。


JVMLSへの行き方

JVMLSの会場はOracleのサンタクララ キャンパスです。いわゆるシリコンバレーと呼ばれるところですね。

日本からだと、
  1. サンノゼ空港直行便
  2. 乗り継ぎでサンノゼ空港
  3. サンフランシスコ空港から陸路
のいずれかの方法で現地入りします。

日本からサンノゼへの直行便は今のところZIPAIRだけです。コロナ前まではANAにもあったのですが、今は運休中です。

乗り継ぎの場合、ロスアンジェルスかシアトルが一般的ですね。

サンノゼ空港からオラクルのキャンパスはそばなのですが、歩いたら1時間ぐらいかかります。バスや鉄道もあるにはあるのですが、本数がとても少ないです。

なので、ホテルまではUberかLyftを使うのがお勧めです。

今回、私は最後のサンフランシスコ空港を使う方法で現地入りしました。サンフランシスコ空港からサンタクララまではBARTとCaltrainという鉄道を乗りついで向かいます。ただ、Caltrainは本数が少ないので、駅で1時間ぐらい待つこともあります。

Caltrainの駅からは、UberかLyftを使うのがお勧めです。車社会なのですが、タクシーはほとんど走っていないので、UberもしくはLyftは必須のアプリです。

宿泊

Oracleのサンタクララキャンパスは市街地ではなく、まわりにはテック系企業の建物がポツン、ポツンとある程度です。

そのため、ホテルもまばらにある感じです。


青いスーツケースのピンがOracleの会場になります。

宿泊するホテルの候補になりそうなのが次の5ホテルぐらい。


一番近いのが、1番のHyatt House。Hyatt Houseは小規模のショッピングモールであるRivermark Plazaにあります。上の地図だと一番右にあるホテルです。

Rivermark Plazaには、スーパーのSafewayやメキシカンのファストフードのChipotleなどもあり、利便性も高いです。

次に近いのがElementです。Elementはまだできたばかりの新しいホテルです。

Elementと一緒にStarbucksなどの複数の店舗も一緒にオープンしたのですが、イマイチ使い勝手はよくないです。スタバも妙に早く閉まるし...

どちらもビジネスホテル的なホテルですけど、日本の価格から考えるとかなり高いです。

Delta Hotelsはコロナ前まではBaltimore Hotelだったのですが、マリオットに買収されて名前が変わっていました。買収前はもっと安かったのですが、マリオット系列になって高くなってしまいました。

ここはハイウェイに面しているので、モーテル的な感じです。ホテルがポツンとあるだけで、Elementの方に行かないと店はない感じです。

Avatarはリーズナブルなホテルだったのですが、残念ながら休業中。ちなみに、Avatarから会場まで、徒歩で40分ぐらいかかります。

Avatarに隣接して、Avatarの朝食会場でもあるIHOPがあったのですが、廃業してました。IHOPのホットケーキ甘すぎなんですけど、たまに食べてみたくなるんですよね。

Avatarから会場に向かう途中にあるのが、Marriottです。敷地も広く、ホテル内にもいろいろ店があるのでいいのですが、なにぶんにも高い。会社が宿泊費を出してくれることでもないかぎり泊まれない感じですね。


今回、櫻庭はElementに宿泊しました。新しいのはいいのですが、やっぱりスーパーが近くにないのはちょっと痛い。

会場まで直線距離だと近いのですが、鉄道が通っているため迂回しなくてはならず、だいたい徒歩で20分ぐらいかかります。

気候

サンタクララは一年中暖かく、乾燥しているので、カラッとした気候です。日中は30℃を超えますが、夜は20℃ぐらいまで下がります。

JVMLSの会場も冷房がきついので、一枚羽織るものを持っていくといいと思います。

会場

会場のOracle AuditoriumはAgnews Historic Parkという公園の一角にあります。
_DSC0442

ここは元々病院だった建物を歴史的建造物として保存してある公園です。とはいうものの、病院のメインの建物から裏側はOracleのサンタクララキャンパスになっています(ちゃんと新しい建物もたってます)。
_DSC0959

このサンタクララキャンパスは以前はSun Microsystemsだったのですが、今はOracleです。Sunの時代の名残として、キャンパスをぐるりと一周する道はNetwork Circleで、Sun Fire Wayという道もあります。
_DSC0634 _DSC0462
会場のAuditoriumは古い講堂で、内部はドーム型になってます。なかなか趣のある建物です。
_DSC1170 _DSC2002

食事

JVMLSでは朝食とランチが出ます。また、2日目の夜にはレセプションがありますが、会場で軽食を食べるぐらいです。

なので、期間中は夕ご飯だけ自分で食べに行かないといけません。

ホテルがポツン、ポツンとあるのと同じようにレストランも散らばっています。Hyatt HouseのあるRivermark PlazaにはChipotoleなどのファストフードや、普通のレストランもあります。

これ以外だと、基本的にUber/Lyftで行く感じです。

今回何を食べたか列挙しておきます。

6日のBirks以外はすべてUber/Lyft利用です。

Birksはステーキ。ここは最近オープンした店のようです。
_DSC0556

7日のBanana LeafはJenkinsの作者であり、LaunchableのCEOである川口耕さんに連れて行っていただきました。
_DSC0971 _DSC1044

8日と9日はどちらもベトナム料理なのですが、8日にサンノゼのリトルサイゴンにあるPho Ha Noiにフォーを食べに行ったのですが、閉まっていたので近くにあるBanh Canh 3 Mienに行ったのでした。Bahn Cahnという麺ははじめてだったのですが、伊勢うどんみたいな感じ。

この旅行中、現金を使ったのはこのBanh Canh 3 Mienだけでした。リトルサイゴンは小さい家族経営の店が多いようで、現金だけのところが多いような感じです。

_DSC1569

ところが、後から分かったのですが、リトルサイゴンにはPho Ha Noiは2店舗あり、閉まっていたのは支店で本店の方は開いていたのでした。

で、9日にスタンフォード大学に遊びに行った後、パロアルトでご飯を食べようと街を歩いていたら、昨日行けなかったPho Ha Noiの支店が目の前に。

ということで、2日連続でベトナム料理となったわけです。

ちなみに、10日はOpenJDK Committers' Workshopに参加していた人たちはChipotleに行ったらしいです。



長くなってしまったので、JVMLS本編に関しては次のエントリーで。