Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

How JVM handles `byte` values -- a difference between JLS and JVMS

 Java has a primitive type called `byte`, but the JVM doesn't have opcodes to calculate them. JVM handles them as `int`. It's the reason why we cannot code like:
 Javaにはbyteというプリミティブ型がありますが、JVMにはbyteを演算するためのオペコードが用意されていません。JVMはbyteをintとして演算します。このため、このようなコードを書くことができません。

byte a = 0;
byte b = 0;
byte c = a + b;
byte[] d = new byte[1];
d[0] = a + b;

 We must code it like below. JVM thinks `byte + byte` is `int`, so we need to cast it.
 次のように書く必要があります。`byte + byte`が`int`として扱われるため、キャストが必要なのです。

byte a = 0;
byte b = 0;
byte c = (byte) (a + b);
byte[] d = new byte[1];
d[0] = (byte) (a + b);

 But the JVM specification tells that we can omit this cast when we store to element of `byte[]`. The bastore opcode has a feature to truncate its value to a byte, so we don't have to call i2b opcode.
 ただしJVMの仕様上は、bastoreオペコードがキャスト(切り詰め)の機能を有しているため、byte[]型変数の要素への代入にはキャスト(i2bオペコード)を省略することも可能です。

 For example, this code for Jasmin which creates a bytecodes storing `127+1` to a element of `byte[]`, works well and outputs -128. It's interesting, JLS requires the cast but JVMS doesn't. This difference may come from understandability I think.
 例えば次のコードは127+1をbyte[]の要素に代入するJasminのコードですが、キャストなしにも関わらず-128を出力します。Java言語仕様上は必要だけどJVM仕様上は不要だなんて面白いですね。人間に対するわかりやすさを重視した結果なのでしょうか。