
私たちが普段楽しんでいる缶ビールのアルコール度数は5%前後。
それでも酔ってしまう人はたくさんいますが、オリエントスズメバチはなんとアルコール度数80%でやっとほろ酔いになるくらいだったのです。
⇧ 超弩級ですな...
そして夜に複雑な作業を行ったプログラマは、頭がさえている日中に簡単なタスクを行います。なぜプログラマは、脳が眠りを欲している夜に精神的に消耗する複雑な仕事を行い、脳が活動し頭がさえている日中に単純なタスクを行うのかというと、疲れがプログラマをより優れたコーダーにするからです。
これはバルマー・ピーク(血中アルコール濃度の0.129%から0.138%の範囲において、超人的なプログラミング能力が発揮される現象)と似た現象で、脳が疲れていると集中力は増すのです。
⇧「バルマー・ピーク」に至るまでのアルコール量が想定の範囲外になりそう...
そも、JavaのValhalla Projectとは?
⇧ に参加してきて、「Valhalla Project」の「Value Class」が必要となった経緯などが分かったので備忘録として。
※ 2024年10月28日(月)時点では、「Vallhara Project」の「Value Class」はプレビュー機能で利用できるものらしいので、正式版のリリースに反映されるまでは、まだ時間がかかりそうとのこと。
他にも、良いセッションがあったので、時間があればどこかのタイミングで整理したいところです。
では、備忘録をまとめていきます。
公式のドキュメントによると、
Project Valhalla
Project Valhalla is augmenting the Java object model with value objects, combining the abstractions of object-oriented programming with the performance characteristics of simple primitives. Supplementary changes to Java’s generics will carry these performance gains into generic APIs.
This Project is sponsored by the HotSpot Group.
⇧ とありますと。
日本の「Java Champion」の1人目であられる「櫻庭祐一」さんの公開されている資料によりますと、
⇧ 上記の話に付いて議論されているのが、「Vallhara Project」ということらしい。
進捗状況が分からんのだけど、
| No | 機能 | JEP | 説明ページURL |
|---|---|---|---|
| 1 | Value Class | 401 | https://openjdk.org/jeps/401 |
| 2 | Null-Restricted Type | draft | https://openjdk.org/jeps/8316779 |
| Nullable Type | |||
| 3 | Enhanced Primitive Boxing | 402 | https://openjdk.org/jeps/402 |
| 4 | Specialized Generic | - | - |
⇧ 上記のような感じで、まだまだ終わりは見えない状況であるらしい。
英語版のWikipediaによりますと、
Project Valhalla is an experimental OpenJDK project to develop major new language features for Java 10 and beyond. The project was announced in July 2014 and is an experimental effort by Oracle, led by engineer Brian Goetz.
https://en.wikipedia.org/wiki/Project_Valhalla_(Java_language)
⇧ 2014年頃にプロジェクトについての発表があったらしいので、彼是10年は経過していることになるのだが、未だ道半ばといった感じではある。
JavaのValhalla ProjectのValue Classが必要となっている経緯など
ズバリ、パフォーマンスを良くしたかったということらしい。
どういうことか?
Value Objects はメモリ上に直接展開可能なデータで、メモリレイアウトを効率化することができます。
しかしこれは、あくまでJavaVMの中の話で、プログラミング言語Javaを扱うプログラマー視点で見た場合、オブジェクトの可変性 / 不変性という特性や、同値判定をする際に equalsメソッドを使うか、==演算子を使うかという形でしか実感しにくいものであろうと思います。
⇧ とありますように、「メモリ」が効率的に利用できていない状態らしいですと。「Vallhara Project」が導入されていない現状だと、「ヒープメモリー」の好き勝手な場所にデータが展開されてる状態らしく、「フラグメンテーション」のように「パフォーマンス」が劣化してるような感じになっているみたい。
「フラグメンテーション」はというと、
フラグメンテーション(fragmentation)、断片化(だんぺんか)とは、コンピュータ上のメモリの管理上の一単位が、そのままでは有効利用できない状態になることを言う。
具体的には、使用中のメモリ領域がわずかな大きさの未使用領域を挟んで飛び飛びに配置され、連続した未使用領域が大きく確保できなくなる状態を言う。 このような状態に陥ると、メモリ領域の新たな確保、走査に時間がかかるため、コンピュータのパフォーマンスが低下する傾向にある。
⇧ という感じらしい。
「Java」が処理されるには「Java 仮想マシン(JVM:Java Virtual Machine)」が必要なわけなのだけど、
A Java virtual machine (JVM) is a virtual machine that enables a computer to run Java programs as well as programs written in other languages that are also compiled to Java bytecode. The JVM is detailed by a specification that formally describes what is required in a JVM implementation. Having a specification ensures interoperability of Java programs across different implementations so that program authors using the Java Development Kit (JDK) need not worry about idiosyncrasies of the underlying hardware platform.
⇧ 上図にあるように、「JVM Memory」部分にデータが展開されるわけなのだけど、データによって管理される場所が異なるらしい。
By the way、
⇧ 上記サイト様にありますように、
- Java Virtual Machine Specification
- Java Language Specification
仕様が異なるらしいのだけど、
⇧ データ型としては、大きく分けて、
- primitive types
- reference types
の2種類に分けられると。
で、「Value Class」は、
⇧「2. reference types」のデータの持ち方を脱却することを目指していると。
■non Value Class(従来のクラス)
■Value Class
⇧上図の「non Value Class(従来のクラス)」で言うところの「Adder」のオブジェクトが配置されている、所謂「Heap領域」を利用させたくないってことみたい。
公式のドキュメントの説明によると、
Description
A value object is an object that does not have identity. A value object is an instance of a value class. Two value objects are the same according to == if they have the same field values, regardless of when or how they were created. Two variables of a value class type may hold references that point to different memory locations, but refer to the same value object—much like two variables of type int may hold the same int value.
An identity object is an object that does have identity: a unique property associated with the object when it is created. Prior to value classes, every object in Java was an identity object. Two identity objects are the same according to == if they have the same identity. Two variables of an identity class type refer to the same identity object only if they hold references pointing to the same memory location.
At run time, the use of value objects may be optimized in ways that are difficult or impossible for identity objects. This is because value objects, untethered from any canonical memory location, can be duplicated, re-encoded, or re-used whenever it is convenient for the JVM to do so. This freedom allows for smaller memory footprint, fewer memory allocations, and better data locality.
Existing classes that represent simple domain values and that have followed best practices to avoid identity dependencies can be easily migrated to be value classes, with minimal compatibility impact. This JEP migrates a handful of commonly-used classes in the Java Platform, including the primitive wrapper classes such as Integer.
⇧「value class」をインスタンス化した「value object」は「identity」を持たないとありますと。
つまり、従来のクラスであれば、Aクラスがあったとして、インスタンス化して全く同じ内容(全てのフィールドの値が同一)の2つのオブジェクト、
- Aオブジェクト1
- Aオブジェクト2
を存在させた場合、各々の「identity」が異なることで識別できたわけなのだが、「value object」は「identity」を持たないので、各々のオブジェクトは全く同じものと見なされてしまうと。
ちなみに、
“Codes like a class, works like an int!”
⇧という言葉は、
モハメド・アリ(Muhammad Ali、英語発音: [muˈhɑməd ɑːˈliː]、1942年1月17日 - 2016年6月3日)は、アメリカ合衆国の元プロボクサー、アクティビスト。ケンタッキー州ルイビル出身。元WBA・WBC世界ヘビー級統一王者。ローマオリンピックライトヘビー級金メダリスト。
人物
蝶のように舞い、蜂のように刺す(Float like a Butterfly, Sting like a Bee)という著名なフレーズは、アリのトレーナーのドリュー・バンディーニ・ブラウンがアリのフットワークとパンチを形容したもので、試合前によく肩を組んで「蝶のように舞い、蜂のように刺す!」と一緒に叫ぶパフォーマンスを見せていた。
⇧ 上記の
『蝶のように舞い、蜂のように刺す(Float like a Butterfly, Sting like a Bee)』
にインスパイアされたものらしい。
正式リリースではないが、JDK 23(Vallhara Projectお試し)を導入してみる
公式のドキュメントによると、
⇧ 導入方法としては、
の2パターン用意されている模様。
「GitHub」で公開されている手順で導入する場合は、「JDK(Java Development Kit)」の形にするには、ビルドが必要っぽい。
「OpenJDK」の一般的なビルドの手順については、
⇧ 上記で紹介されているのだが、如何せん、「Linuxディストリビューション」が「Debian」系の場合しか載せてくれていないんだわ...
「Docker Hub」が公開している「OpenJDK」のDockerイメージのページから、
⇧ 各ベンダーの「OpenJDK」のリンクが載っているので、試しに、「eclipse-temurin」を選択します。
ページ遷移後、「Dockerfile」のリンクをクリック。
各「Linuxディストリビューション」用の「Dockerfile」のリンクが掲載されているので、
「23.0.1_11-jdk-ubi9-minimal」を選択してみると、
⇧「RHEL 9(Red Hat Enterprise Linux 9)」系に必要な依存ライブラリとか確認できる。
「Red Hat」のログインなどを不要とするには、
⇧ 上記サイト様のように、ベースイメージを変える必要があるみたい。
脱線しましたが、
■Dockerfile
# RHEL 9(Red Hat Enterprise Linux)
FROM registry.access.redhat.com/ubi9/ubi-minimal:latest
RUN microdnf update -y \
&& microdnf install -y \
gzip \
tar \
# Required for jlink
binutils \
wget \
# utilities for keeping UBI and OpenJDK CA certificates in sync
# https://github.com/adoptium/containers/issues/293
ca-certificates \
jq \
# java.lang.UnsatisfiedLinkError: libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory
# java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager
# https://github.com/docker-library/openjdk/pull/235#issuecomment-424466077
fontconfig \
glibc-locale-source \
tzdata \
git \
vim
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 \
&& echo LANG=ja_JP.UTF-8 > /etc/locale.conf
RUN microdnf remove -y glibc-locale-source \
&& microdnf clean all \
&& ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
ENV LANG="ja_JP.UTF-8" \
LC_ALL="ja_JP.UTF-8" \
TZ="Asia/Tokyo"
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
#■
#■ JDKのインストール
#■
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# https://jdk.java.net/valhalla/
# Build 23-valhalla+1-90 (2024/7/26)
# Linux?/?x64 tar.gz (sha256) 206327187
RUN wget https://download.java.net/java/early_access/valhalla/1/openjdk-23-valhalla+1-90_linux-x64_bin.tar.gz -O /tmp/openjdk.tar.gz
# https://download.java.net/java/early_access/valhalla/1/openjdk-23-valhalla+1-90_linux-x64_bin.tar.gz.sha256
ARG ESUM='5235afaf5ecc86f2237458cf40f8ed965939372f606edbd0fc46e1ee2e69f5f5'
ENV JAVA_HOME=/opt/java/openjdk
ENV PATH=$JAVA_HOME/bin:$PATH
RUN set -eux; \
echo "${ESUM} */tmp/openjdk.tar.gz" | sha256sum -c -; \
mkdir -p "$JAVA_HOME"; \
tar --extract \
--file /tmp/openjdk.tar.gz \
--directory "$JAVA_HOME" \
--strip-components 1 \
--no-same-owner; \
rm /tmp/openjdk.tar.gz
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
#■
#■ Gradleのインストール
#■
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
RUN microdnf install -y \
unzip \
&& microdnf clean all
RUN GRADLE_VERSION=8.3 \
&& wget https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -O /tmp/gradle.zip \
&& unzip /tmp/gradle.zip -d /opt/ \
&& ln -s /opt/gradle-${GRADLE_VERSION} /opt/gradle \
&& rm /tmp/gradle.zip
ENV PATH=$PATH:/opt/gradle/bin
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
#■
#■ 作業用ユーザーの追加
#■
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ユーザー追加用
ARG USER_ID=1000
ARG GROUP_ID=1000
ARG USER_NAME=myuser
ARG GROUP_NAME=myuser
ARG USER_PASS=password
# sudoをインストール
RUN microdnf install -y \
sudo \
&& microdnf clean all
# ユーザーとグループの作成
RUN groupadd -g ${USER_ID} ${GROUP_NAME} \
&& useradd -m -s /bin/bash -u ${USER_ID} -g ${GROUP_ID} -G wheel ${USER_NAME} \
&& echo ${USER_NAME}:${USER_PASS} | chpasswd \
&& echo "${USER_NAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# ユーザーの切り替え
USER ${USER_NAME}
WORKDIR /home/${USER_NAME}
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
#■
#■ Dockerコンテナ起動時
#■
#■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# Exited(0)でコンテナが終了するのを回避する
CMD ["tail", "-f", "/dev/null"]
⇧ のような感じで「Dockerfile」を、「Linux」環境に作成・配置します。


Dockerfile を元にDockerイメージを作成する。
docker build . -t [NAME]

Dockerコンテナにログインする。
docker exec -ti [コンテナ名] bash

とりあえず、「Pointer.java」と「Main.java」を作成する。ファイルの「所有ユーザー」「所有グループ」は、「javac」「java」「jshell」などを実行するユーザーに合わせておかないとエラーになるので要注意。

■Pointer.java
value class Pointer{
private int x;
private int y;
Pointer(int x, int y){
this.x = x;
this.y = y;
}
}

■Main.java
class Main {
public static void main(String[] args){
Pointer pointer_01 = new Pointer(0, 0);
Pointer pointer_02 = new Pointer(0, 0);
boolean value = (pointer_01 == pointer_02);
System.out.println(value);
}
}

■JDK 23のプレビュー機能を利用してJavaファイルをコンパイル
javac --enable-preview --release 23 *.java
■JDK 23のプレビュー機能を利用してJavaのクラスファイルを実行
java --enable-preview Main

⇧ 上記のような感じで、「Value Class」から作成したオブジェクトは、同一と見なされてしまうことが確認できました。
業務で利用していたJavaのバージョンが8なので、浦島太郎な気分です...
毎度モヤモヤ感が半端ない…
今回はこのへんで。













