投稿日: 2015/12/13 14:00:53
jjsに-scriptingオプションを指定すると、文字列の中に${expr}という形式でexprの部分に変数名や計算式を埋め込むことができます。コンストラクタや代入を埋め込むこともできます。
${expr}はexprの部分をそのままeval()に渡しているのかと思ったのですが、バイトコードを見た限りではeval()は使用されておらず、例えば"A${x+9}Z"は("A"+(x+9)+"Z")に相当する処理に変換されるようです。
1-1. 実行するスクリプト(stringInterpolation.js)
var s = "A";var n = 10;print("s+1=${s+1}, n+1=${n+2}, s.aaa=${s.aaa}, [3,4]=[${[3,4]}]");print("new java.awt.Point(5,6)=${new java.awt.Point(5,6)}");print("(function(x)x*7)(8)=${(function(x)x*7)(8)}");var t = null;print("(t=s)=${t=s}=(t)=${s}");1-2. jjsで実行する
>jjs -scripting -fullversion stringInterpolation.jsnashorn full version 1.8.0_66-b18s+1=A1, n+1=12, s.aaa=undefined, [3,4]=[3,4]new java.awt.Point(5,6)=java.awt.Point[x=5,y=6](function(x)x*7)(8)=56(t=s)=A=(t)=A2-1. バイトコードを確認するためのスクリプト(stringInterpolationByteCode.js)
var x = "s";print("A${x+9}Z");2-2. jjsに-pc(--print-code)オプションを付けてバイトコードを確認する(抜粋)
>jjs -scripting -fullversion -co=true -pc stringInterpolationByteCode.jsnashorn full version 1.8.0_66-b18class: jdk/nashorn/internal/scripts/JO1P0// class version 51.0 (51)// access flags 0x21...L3 [bci=29]<line 2> 29 aload 2 30 invokedynamic dyn:getMethod|getProp|getElem:print(Object;)Object; [static 'bootstrap' fastscope] 35 getstatic ScriptRuntime.UNDEFINED : Undefined; 38 ldc "A" 40 aload 2 41 invokedynamic dyn:getProp|getElem|getMethod:x(Object;)Object; [static 'bootstrap' fastscope] 46 bipush 9 48 invokestatic Integer.valueOf(I)Integer; 51 invokestatic ScriptRuntime.ADD(Object;Object;)Object; 54 invokestatic ScriptRuntime.ADD(Object;Object;)Object; 57 ldc "Z" 59 invokestatic ScriptRuntime.ADD(Object;Object;)Object; 62 invokedynamic dyn:call(Object;Undefined;Object;)Object; [static 'bootstrap' fastscope]