java jdb如何评估多行代码?

问题描述 投票:0回答:2

像for循环

有没有动态评估代码的解决方案?

eval 也不支持

import
关键字。

main[1] eval java.lang.Class.forName("java.util.stream.IntStream").getDeclaredMethods()
 java.lang.Class.forName("java.util.stream.IntStream").getDeclaredMethods() = instance of java.lang.reflect.Method[51] (id=767)

main[1] print java.util.stream.IntStream.range(0, 3)
 java.util.stream.IntStream.range(0, 3) = "java.util.stream.IntPipeline$Head@67b64c45"

main[1] eval java.util.stream.IntStream.range(0, 3).forEachOrdered(n -> { System.out.println(n); })
com.sun.tools.example.debug.expr.ParseException: Name unknown: n
 java.util.stream.IntStream.range(0, 3).forEachOrdered(n -> { System.out.println(n); }) = 空值

Java 传统的 for 循环也不支持。

main[1]
main[1] eval  for (int i = 1; i <= 10; i++) {
            System.out.println(i);
无法识别的命令: 'system.out.println(i);'。请尝试获得帮助...
main[1]         }com.sun.tools.example.debug.expr.ParseException: Encountered " "for" "for "" at line 1, column 3.
Was expecting one of:
   

java debugging jdb
2个回答
0
投票

在 jdb 会话中,如果运行

help
,那么你可能会看到类似这样的内容:

Initializing jdb ...
> help
** command list **
...

print <expr>              -- print value of expression
dump <expr>               -- print all object information
eval <expr>               -- evaluate expression (same as print)
...

并且eval的描述说评估表达式,所以它不是评估语句,这是你真正想要的,如果我错了,请纠正我,谢谢!


0
投票

答案是你不能。

jdb
并没有实现完整的Java编译器,而是在
expr
文件夹中(在examples.jar中找到)实现了一个“迷你”表达式计算器,其语法是用JavaCC编写的(
Expr.jj
)。它使用它为some Java 表达式构建有效 AST 的子集。它在内部将
import
列为关键字,但使用它实际上是一个错误,因为它的语法并不真正支持关键字...

main[1] print import java.lang.*;
com.sun.tools.example.debug.expr.ParseException: Encountered "import" at line 1, column 2.
Was expecting one of:
    "false" ...
    "new" ...
    "null" ...
    "super" ...
    "this" ...
    "true" ...
    <INTEGER_LITERAL> ...
    <FLOATING_POINT_LITERAL> ...
    <CHARACTER_LITERAL> ...
    <STRING_LITERAL> ...
    <IDENTIFIER> ...
    "(" ...
    "!" ...
    "~" ...
    "++" ...
    "--" ...
    "+" ...
    "-" ...

因此,除其他含义外,您想要在

import
表达式中“
jdb
”的任何内容都需要(相反)拼写出其 FQN,例如你需要
java.lang.String
不仅仅是
String
等等

if
for
这样的关键字在 jdb 的
expr
语法中也不起作用。但对于
if
,您有支持三元条件运算符
?:
的解决方法。

main[1] print 1 > 2 ? "yes" : "no"
 1 > 2 ? "yes" : "no" = "no"

此外,

jdb
set
,您可以使用它来设置字段。看看它的
makeName
代码,它似乎也想支持设置局部变量(如果调试者有该信息,即用
javac -g
编译),但你绝对不能创建新的局部变量。任何不合格的名称都必须是现有名称,显然是在当前(堆栈)帧中解释的。如果你写
x = 1
,改变这些通常不是你想要的/专家,但我想它可能有用......但它对我来说根本不起作用,无论是读取或写入局部变量,甚至对于编译的东西与
-g
。可能我在这方面遗漏了一些东西(语法方面)或者它有一些错误。无论如何,
jdb
中没有任何类型的“调试器端”槽或变量,可以在其中保存“内容”,例如先前表达式的结果;这一切都必须在调试对象中完成,并且只有字段才能可靠地实现此目的。因此(除非调试者带有可以滥用用于此类目的的字段),使用复杂的表达式有点麻烦,因为您需要内联所有参数/表达式。

在 JDK 1.9+ 中,他们添加了

jshell
用于多行评估,并提供更丰富的 Java 语法支持,但 AFAICT
jshell
无法进行调试。

© www.soinside.com 2019 - 2024. All rights reserved.