Slide 1

Slide 1 text

Javaの現状2024夏 2024-07-19 JJUG CCC 2024 Spring報告会 LINEヤフー きしだ なおき

Slide 2

Slide 2 text

Javaの現状2024夏 ● Javaと教育 ● Javaと現代的プログラミング ● Javaで動かすAI

Slide 3

Slide 3 text

Javaと教育 ● Java in Education ● いまJavaを勉強する意味 ● 教育向けの対応

Slide 4

Slide 4 text

Java in Education ● https://groups.io/g/EducationInJava ● 2020から活動してるっぽい ● こういう地味な活動がJavaは強い

Slide 5

Slide 5 text

いまJavaを勉強する意味 ● シェア ● 大規模Webサービスや金融ではやはり強い ● JVM ● 性能と信頼性 ● 進化 ● 出遅れて進化してるので、いま見てておもしろい ● 言語 ● 欠点はあるけど、そこまで悪くない。必要な機能はそろっている

Slide 6

Slide 6 text

教育向けの対応 ● Pythonが強いので対策が進められている ● Paving the on-ramp(Sep. 2022) ● (進入路を舗装する) ● https://openjdk.org/projects/amber/design-notes/on-ramp ● 学習しやすさのための機能 ● JShell(Java 9) ● javaコマンドでの実行(Java 11) ● クラスの省略(Java 22 preview) ● System.outの省略(Java 23 preview) ● Playground ● dev.java/playground

Slide 7

Slide 7 text

JShell ● REPL(Read-Eval-Print Loop) ● 対話的な実行 ● 「Javaのプログラムの実行は面倒」への対応 ● ただし実際のプログラミングとは別になってしまう >jshell | JShellへようこそ -- バージョン22 | 概要については、次を入力してください: /help intro jshell> 2+3 $1 ==> 5 jshell> var data = List.of("aa", "bb", "cc") data ==> [aa, bb, cc] jshell> data.stream().map(String::toUpperCase).collect(Collectors.joining("/")) $3 ==> "AA/BB/CC"

Slide 8

Slide 8 text

javaコマンドでの実行 ● ソースファイルを直接javaコマンドで実行 ● 「Javaのプログラムの実行は面倒」への対応 ● javac、javaコマンドの連携は初心者は間違いがち ● javacコマンドには.javaファイル、javaコマンドには.classファイル >more hello.java public class Main { public static void main(String[] args) { System.out.println("Hello"); } } >java hello.java Hello

Slide 9

Slide 9 text

クラスやパブリックスタティックヴォイドメインの省略 ● publicとかclassとかstaticとか配列とか、いきなりわからない ● 「おまじない」 ● classの省略可能 ● mainメソッドはpublicやstaticじゃなくていい ● 引数もなくていい >more hello.java void main() { System.out.println("Hello"); } >java --enable-preview --source 22 hello.java Hello

Slide 10

Slide 10 text

System.outの省略 ● System.outもよくわからない ● 9月リリースのJava 23で、クラスを省略したときにはSystem.outも省 略できるようになる。 ● ちょっとルールがめんどう >more hello.java void main() { println("Hello"); } >java\jdk\jdk-23-b29\bin\java --enable-preview --source 23 hello.java Hello

Slide 11

Slide 11 text

Playground ● そもそもインストールめんどう ● ブラウザで直接ためしたい ● https://dev.java/playground/

Slide 12

Slide 12 text

Javaと現代的プログラミング ● Lambda式(Java8) ● ローカル変数型推論(Java11) ● パターンマッチング(Java16-) ● 代数的データ型 ● 軽量スレッド(Java 21)

Slide 13

Slide 13 text

Lambda式 ● 関数型プログラミングの隆盛 ● 関数を値として扱えるプログラミングスタイル ● Webはリクエスト-レスポンスの関数的 ● メソッドひとつのインタフェースのオブジェクトを関数として扱う ● 関数を値として扱えるわけではないけど、主要な用途をまかなえる Function fn = new Function<>() { public String apply(Integer n) { return "hello".repeat(n); } }; Function fn = n -> "hello".repeat(n)

Slide 14

Slide 14 text

ローカル変数型推論 ● 型を書くのは面倒 ● 特に、newでは同じ型を書く必要があって冗長 ● Rubyの流行で型を書かないことが流行る ● Scalaの登場で型推論が流行る ● ダイヤモンド型推論で型推論機構自体はもっていた ● ローカル変数は寿命が短いので型がなくても理解できる ArrayList strs = new ArrayList<>(); ArrayList strs = new ArrayList(); var strs = new ArrayList();

Slide 15

Slide 15 text

パターンマッチング ● instanceof ● 基本的なパターンマッチ機構の導入 ● record ● 値保持用のクラスを定義 ● パターンマッチングで値の分解 ● switch ● パターンマッチングによる分岐 record MyRecord(String s, int n) {} var a = switch(o) { case String s -> s.length(); case MyRecord(_, var n) -> n; default -> 0; }

Slide 16

Slide 16 text

代数的データ型 ● 代数: 掛算と足算 ● record ● 直積型: 型の掛算 ● record Value(boolean a, byte b){} ● boolean(2通り) x byte(256通り)で512通りの値を保持 ● sealed class ● 直和型: 型の足し算 ● sealed interface Value { record BooleanValue(boolean v) {} record ByteValue(byte v) {} } ● boolean(2通り) + byte(256通り)で258通りの値を保持

Slide 17

Slide 17 text

軽量スレッド ● Javaが持っているスレッドはOSサポートのスレッド ● 多機能で複数CPUコアを使いこなせる ● Webサーバーでは複数のリクエストのためにスレッドを使う ● 通信時にCPUを遊ばせたくない ● そのための並列動作としてはOSスレッドは重い ● 仮想スレッド ● JVM管理の軽量スレッド Thread.ofVirtual(() -> proc()).start()

Slide 18

Slide 18 text

Javaで動かすAI ● Python全盛ではあるけど、仕組み的な強さはないのでワンチャン ありそう(先はとても長い) ● 動かし方 ● サーバーをたてて呼び出す ● llama.cppをネイティブライブラリとして呼び出す ● 全部Javaで書く

Slide 19

Slide 19 text

サーバーをたてて呼び出す ● 外部で動いているAIサーバーを呼び出す ● 例: Azure OpenAI クライアントライブラリ ● 「Javaで動かす」とは言い難い

Slide 20

Slide 20 text

llama.cppをライブラリとして呼び出す ● llama.cpp – C++で書かれたLLM実装 ● Foreign Function API

Slide 21

Slide 21 text

全部Javaで書く ● Jlama ● llama2.java ● Foreign Memory APIとVector API ● 基本型を定義できるProject Valhallaが必要 // matmul final int SIMD_SIZE = SPECIES.length(); final long FLOAT_SIZE = ValueLayout.JAVA_FLOAT.byteSize(); FloatVector val = FloatVector.zero(SPECIES); for (int j = 0; j < n; j+=SIMD_SIZE) { FloatVector a = FloatVector.fromMemorySegment( SPECIES, w, (i * n + j + 0*SIMD_SIZE) * FLOAT_SIZE, ByteOrder.LITTLE_ENDIAN); FloatVector b = FloatVector.fromArray(SPECIES, x, j + 0*SIMD_SIZE); val = a.fma(b, val); } xout[i] = val.reduceLanes(VectorOperators.ADD);