为什么JVM允许我们命名以字节码中的数字开头的函数? [英] Why does the JVM allow us to name a function starting with a digit in bytecode?

查看:184
本文介绍了为什么JVM允许我们命名以字节码中的数字开头的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标识符由 Java语言规范,Java SE 7版(§3.8)


<$ p定义良好$ p> 标识符是Java字母和Java数字的无限长度序列,
首先必须是Java字母。


据我所知,因为方法名称是标识符,应该不可能在java中命名以数字开头的方法,并且 javac 遵守此规则。



那么,为什么Java虚拟机似乎不尊重这个规则,允许我们在Bytecode中命名一个以数字开头的函数?






这个简单的代码片段实际上会打印 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());
返回i;
}
}

编译和执行:

  $ javac Test.java 
$ java测试

输出:

  f99 
100

编译后可以反汇编代码,并将所有 f99 重命名为 99 (在 reJ 等工具的帮助下)。

  $ java测试

输出:

  99 
100

那么,该方法的名称实际上是99吗?

解决方案

Java语言规范限制了有效方法名称中的字符,以帮助明确解析Java语言。



JVM旨在支持除了Java之外的语言。因此,限制不应该相同;除非我们想强制所有非Java语言具有相同的限制。为JVM选择的限制是允许对方法签名进行明确解析的最小集合,这种格式出现在JVM规范中而不是JLS中。



取自 JVM Spec

 名称不得包含任何ASCII字符。 ; [/< > :

也就是说,以下是有效的JVM签名 [Lcom / foo / Bar; ,其特殊字符已从方法名称中排除。



<> 进一步保留用于将特殊JVM方法与应用程序方法分开,特别是< init> < clinit> ,这两个都是JLS不允许的方法名称。


Identifiers are well defined by The Java Language Specification, 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.

As far as I know, since a method name is an identifier, It should be impossible to name a method starting with a digit in java, and javac respects this rule.

So, why does the Java Virtual Machine seem to not respect this rule by allowing us to name a function starting with numbers, in Bytecode?


This simple snippet will actually print the f99() method name and the value of its parameter.

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;
    }
}

Compilation and execution:

$ javac Test.java
$ java Test

Output:

f99
100

It is possible to disassemble the code once compiled, and rename all f99 occurences by 99 (with the help of a tool like reJ).

$ java Test

Output:

99
100

So, is the name of the method actually "99"?

解决方案

The Java Language Specification restricts the characters in valid method names so as to help make parsing the Java language unambiguous.

The JVM was designed to be able to support languages other than just Java. As such the restrictions should not be the same; unless we wanted to force all non-Java languages to have the same restrictions. The restrictions chosen for the JVM are the minimal set that permit unambiguous parsing of the method signatures, a format that appears in the JVM spec and not the JLS.

Taken from the JVM Spec

a name must not contain any of the ASCII characters . ; [ / < > :

That is, the following is a valid JVM signatures [Lcom/foo/Bar;, and its special characters have been excluded from method names.

<> was further reserved to separate special JVM methods from application methods, specifically <init> and <clinit>, which are both method names that the JLS does not permit.

这篇关于为什么JVM允许我们命名以字节码中的数字开头的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆