问题描述
Java语言规范对有效方法名称中的字符进行了限制,以帮助解析Java语言。
JVM设计为能够支持Java以外的其他语言。因此,限制不应相同;除非我们要强制所有非Java语言都具有相同的限制。为JVM选择的限制是允许对方法签名进行明确解析的最小设置,这种格式出现在JVM规范而非JLS中。
取自JVM Spec
a name must not contain any of the ASCII characters . ; [ / < > :
也就是说,以下是有效的JVM签名[Lcom/foo/Bar;
,并且其特殊字符已从方法名称中排除。
<>
进一步保留了将特殊的JVM方法与应用程序方法分开的方法,特别是<init>
和<clinit>
,这都是JLS不允许的方法名称。
解决方法
标识符在 Java SE 7 Edition (第3.8节)中明确定义。
An identifier is an unlimited-length sequence of Java letters and Java
digits,the
first of which must be a Java letter.
据我所知,由于方法名是一个标识符,因此在Java中以数字开头的方法应该是不可能的,并且javac
遵守这一规则。
那么,为什么Java虚拟机似乎不允许我们以字节码命名以数字开头的函数,所以似乎不遵守该规则?
这个简单的代码片段实际上将打印f99()
方法名称及其参数的值。
public class Test {
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.f99(100));
}
public int f99(int i){
System.out.println(Thread.currentThread().getStackTrace()[1].getMethodName());
return i;
}
}
编译与执行:
$ javac Test.java
$ java Test
输出:
f99
100
可以在编译后反汇编代码,并f99
通过99
(在诸如reJ之类的工具的帮助下
)重命名所有出现的代码。
$ java Test
输出:
99
100
那么,该方法的名称实际上是“ 99”吗?