ブログ

新型コロナウイルス関連

新型コロナウイルスワクチン接種

本日,東京大手町の自衛隊東京大規模接種センターに行き,新型コロナウイルスのワクチン接種を受けてきました。まったく痛みはなく,注射針を刺されたことがわかりませんでした。副反応は1回目の接種で5割,2回目の接種で8割の人が何らかの異常を呈するそうなので,何かはあると覚悟しています。

新型コロナウイルス関連

IOCに質問

日本政府,東京都,JOCがはっきりした説明をしてくれないので,IOC(ジュネーブ)に質問メールを送りました。

Dear. International Olympic Committee.

  Hi, I am KUBO, an inhabitant in Tokyo. I have a question about the Olympic Game 2020 Tokyo. But all of Japanese Government, Tokyo Metropolitan government and Japanese Olympic Committee make ambiguous explanations. Would you give me a definite answer?

 Will the Olympic Game 2020 Tokyo, which was postponed a year, be held?  Dr. OMI, Shigeru, who is former regional director of WHO western Pacific region, says "Under infection circumstance (of COVID-19) nowadays, we usually do not  hold". Because the expert on infection says like this, I will evacuate from Tokyo if the Olympic Game be held. I must make  reservations for accommodations before long.

<参考訳>
親愛なる国際オリンピック委員会様

私は東京の住民で久保と申します。東京オリンピック2020について質問があります。しかし,日本政府,東京都,日本オリンピック委員会のすべてが曖昧な説明をしています。はっきりした回答を頂けますでしょうか?

 1年延期されていた東京オリンピック2020は開催されるのでしょうか? 尾身茂先生(元WHO西太平洋地域事務局長)は,「今の(COVID-19)の感染状況では,普通はやらない」と述べました。感染症の専門家がこのようにおっしゃるので,もしオリンピックが開かれるのであれば私は東京から避難します。まもなく宿泊の手配をしなければなりません。

雑記

世界らん展2021

世界らん展2021に行きました。例年,東京ドームで開催されているイベントですが,今年はコロナ禍の影響からか,東京ドームではなくその脇にあるプリズムホールでの開催となってしまいました。出店も少なく,大したものは買えませんでした。

JDK

Java 16新機能(4)

Stream APIにtoList()メソッドが実装され,StreamからListへの変換が容易に行えるようになりました。これまではStreamのcollectメソッドにCollectors.toList()を渡していました。今後はStreamオブジェクトに対して直接toList()メソッドを実行してList型に格納してくれるようになります。

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class StreamToList
{
	public static void main(String[] args)
	{
		IntStream stream = IntStream.range(1, 100);
		//List<Integer> list = stream.boxed().collect(Collectors.toList());
		List<Integer> list = stream.boxed().toList();
		for(int item : list)
		{
			System.out.printf("%d\t", item);
		}
		System.out.println("");
	}
}

警告:実験的なモジュールを使用しています: jdk.incubator.foreign
警告1個
WARNING: Using incubator modules: jdk.incubator.foreign
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

JDK

Java 16新機能(3)

Java 16からは値ベースのAPIクラス,つまり,プリミティブ型のラッパークラスであるInteger,Long, Float, Double, Booleanなどが非推奨となり,コンパイル時に警告が出されるようになりました。次のような非常に簡単なプログラムをコンパイルしてみると,この振る舞いを確認できます。

public class ValueBased
{
	public static void main(String[] args)
	{
		Integer i = new Integer(1);
		Double d = new Double("123.54");
	}
}

警告:実験的なモジュールを使用しています: jdk.incubator.foreign
ValueBased.java:5: 警告:[removal] IntegerのInteger(int)は推奨されておらず、削除用にマークされています
Integer i = new Integer(1);
^
ValueBased.java:6: 警告:[removal] DoubleのDouble(String)は推奨されておらず、削除用にマークされています
Double d = new Double(“123.54”);
^
警告3個

JDK

Java 16新機能(2)

Java 16では,JDK内部の隠蔽が強化されています。例えば,enumクラスのprotectedメソッドclone()をリフレクションを使って呼び出してみましょう。このメソッドの実装は単にCloneNotSupportedExceptionをスローするだけのものになっています。次のようなプログラムを書いて,JDK11とJDK16での挙動の違いを比較してみます。

JDK11で実行した場合は,CloneNotSupportedExceptionがスローされており,protectedメソッドであるclone()がリフレクションによって実行できていることがわかります。しかし,JDK 16で実行した場合はsetAccessible()メソッドを呼び出した段階で,InaccessibleObjectExceptionがスローされています。そのため,invokeメソッドによってclone()メソッドを呼び出すことができていないことがわかります。

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class StronglyEncapsulate
{
	enum EnumExample { A, B, C; }
	public static void main(final String[] args) throws Throwable
	{
		try
		{
			Method method = Enum.class.getDeclaredMethod("clone");
			method.setAccessible(true);
			String result = (String)method.invoke(EnumExample.A);
			System.out.println(result);
		}
		catch(InvocationTargetException e)
		{
			throw e.getCause();
		}
	}
}

JDK 11での実行結果

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by StronglyEncapsulate to method java.lang.Enum.clone()
WARNING: Please consider reporting this to the maintainers of StronglyEncapsulate
WARNING: Use –illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Exception in thread “main” java.lang.CloneNotSupportedException
at java.base/java.lang.Enum.clone(Enum.java:165)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at StronglyEncapsulate.main(StronglyEncapsulate.java:12)

JDK 16での実行結果

警告:実験的なモジュールを使用しています: jdk.incubator.foreign
警告1個
WARNING: Using incubator modules: jdk.incubator.foreign
Exception in thread “main” java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Object java.lang.Enum.clone() throws java.lang.CloneNotSupportedException accessible: module java.base does not “opens java.lang” to unnamed module @13221655
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at StronglyEncapsulate.main(StronglyEncapsulate.java:11)

JDK

Java 16 新機能(1)

3月16日にJava 16がリリースされました。早速,新しい機能を試してみることにします。

リリースノート(Oracle)

まずは,Foreign Linker APIというものです。これはJavaから他の言語で作成されたネイティブAPIを呼び出す機能です。従来はJNIという仕組みで行っていました。しかし,JNIはC言語のヘッダファイルを用意して呼出規約を定義する必要があり,非常に面倒でした。 Foreign Linker API はまだincubaterという位置づけですが,非常に簡単にネイティブ関数を呼び出すことができる魅力的な機能です。早く正式なAPIとしてJDKに入れて欲しいと願っています。

以下のプログラムではC言語の文字列長を返すstrlen関数を呼び出しています。strlenに”Hello World”という文字列を渡して,文字列の長さが11と返されています。

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import jdk.incubator.foreign.Addressable;
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemorySegment;
public class ForeignLinker
{
	public static void main(String[] args) throws Throwable
	{
		int length = callStrlen("Hello World");
		System.out.println(length);
	}
	public static int callStrlen(String str) throws Throwable
	{
		int result = 0;
		Addressable address = LibraryLookup.ofDefault().lookup("strlen").get();
		MethodType methodType = MethodType.methodType(int.class, MemoryAddress.class);
		FunctionDescriptor descriptor = FunctionDescriptor.of(CLinker.C_LONG, CLinker.C_POINTER);
		CLinker clinker = CLinker.getInstance();
		MethodHandle strlen = clinker.downcallHandle(address, methodType, descriptor);
		try (MemorySegment cString = CLinker.toCString(str))
		{
			result = (int)strlen.invokeExact(cString.address());
		}
		return result;
	}
}

警告:実験的なモジュールを使用しています: jdk.incubator.foreign
警告1個
WARNING: Using incubator modules: jdk.incubator.foreign
11

ちなみにこれをJNIで実現しようとすると,以下のようになります。

[Strlen.java]
public class Strlen
{
    static
    {
        System.loadLibrary("Strlen");
    }
    public static void main(final String[] args)
    {
        Strlen instance = new Strlen();
        int result = instance.execStrlen("Hello World");
        System.out.println(result);
    }
    public native int execStrlen(String arg);
}
[Strlen.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Strlen */

#ifndef _Included_Strlen
#define _Included_Strlen
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Strlen
 * Method:    execStrlen
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_Strlen_execStrlen
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
[Strlen.c]
#include <string.h>
#include "Strlen.h"

JNIEXPORT jint JNICALL Java_Strlen_execStrlen(JNIEnv *env, jobject obj, jstring arg)
{
    const char* bytes = (*env) -> GetStringUTFChars(env, arg, NULL);
    size_t length = strlen(bytes);
    (*env) -> ReleaseStringUTFChars(env, arg, bytes);
    return length;
}
雑記

回線乗換失敗

インターネット回線をケーブルテレビの回線に乗り換えようとしましたが,失敗しました。ケーブルテレビ回線の通信品質があまりにも悪く,業務での使用に堪えるものではありませんでした。確かに下りの速度は高速なのですが,不安定なのです。頻繁に切れてしまいます。これではVPNを使っている時など,何度も接続しなおすことになってしまい仕事が進まなくなります。

やむを得ず,電気通信事業法第二十六条の三に基づき,初期契約解除を断行しました。これはクーリングオフのような制度で,8日以内であれば理由を問わず契約解除できるというものです。使ってみないと品質がわからないという「商品」の特性上,このような制度は欠かせないものと考えます。

しかも,「初期契約解除」制度などについて書かれた契約書面をケーブルテレビの会社からは交付されていません。しかも,「申込書控」には,私が「工事完了の確認サインをお願いします」と言われてタブレット端末に書いたサインがコピーされて印刷され,「初期契約解除等について説明を受けた」という欄に「はい」と印字されていました。勝手にサインをコピーして書類を偽造していたことになります。きわめて不適切な行為ですので,監督官庁である総務省総合通信基盤局電気通信事業部に報告しておきました。

本件に伴い,電話番号変更連絡を差し上げていた皆様には二転三転することとなり申し訳ございません。