ローカル変数の一覧を取得
Posted feedbacks - Java
コンパイルオプションで -g を指定することでクラスファイルにローカル変数名を入れることができるのですが、それを認識するAPIはありません。
クラスパスからクラスファイルを取得・解析してローカル変数名を取得することも多分可能ですが、変数名に対応する値を取得する方法がありません。
どうしようもないので内部クラスを使って似たようなことをやってみました。
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 | import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) {
Map map = foo();
System.out.println(map);
}
static Map foo() {
Map map = new HashMap();
class Hoge {
int x = 1;
String y = "hello";
Hoge() {
}
}
Hoge hoge = new Hoge();
Field[] fields = hoge.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
try {
map.put(fields[i].getName(), fields[i].get(hoge));
} catch (Exception e) {
e.printStackTrace();
}
}
return map;
}
}
|
ローカル変数の取得はリフレクションというよりはデバッグ用という感じがします。
そこで、Java Debug Interface を使ってみました。
public class Sample {
public static void main(String[] args) {
int x = 1;
String y = "hello";
}
}
というサンプルの場合は、-g オプションつきで Sample をコンパイルした後に、
java TinyDB Sample
で起動すると、mainメソッドのローカル変数(引数つき)が出力されます。
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 | import com.sun.jdi.*;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.event.*;
import com.sun.jdi.request.*;
import java.util.Map;
public class TinyDB {
public static void main(String[] args) throws Exception {
LaunchingConnector lc = Bootstrap.virtualMachineManager().
defaultConnector();
Map<String, Connector.Argument> arg = lc.defaultArguments();
arg.get("main").setValue(args[0]);
VirtualMachine vm = lc.launch(arg);
EventQueue q = vm.eventQueue();
EventSet e = q.remove(); // get VMStartEvent
EventRequestManager mgr = vm.eventRequestManager();
MethodExitRequest exitReq = mgr.createMethodExitRequest();
exitReq.addClassFilter(args[0]);
exitReq.enable();
e.resume();
e = q.remove(); // MethodExitEvent
LocatableEvent ev = (LocatableEvent)e.eventIterator().nextEvent();
ThreadReference tr = ev.thread();
StackFrame frame = tr.frame(0);
for (LocalVariable var : frame.visibleVariables()) {
System.out.print(var.name() + ": ");
Value val = frame.getValue(var);
if (val instanceof PrimitiveValue) {
System.out.println(((PrimitiveValue)val).doubleValue());
} else if (val instanceof StringReference) {
System.out.println(((StringReference)val).value());
} else if (val instanceof ObjectReference) {
System.out.println(val.type().name());
}
}
e.resume();
e = q.remove(); // get VMDisconnectEvent
}
}
|


にしお
#3391()
Rating0/0=0.00
Pythonで表現すると、下のコードの???部分を埋めることになります。
>>> def foo(): x = 1 y = "hello" ??? return result >>> foo() {'y': 'hello', 'x': 1}[ reply ]