6

众所周知,在Java中,方法名不足以区分不同的方法。

我认为(可能是错误的),要区分一个方法,它需要以下信息:

(className, methodName, methodParameters)

更远,

  • 如何在内部更有效地识别方法?
  • 我听说过“方法ID”。是不是意味着上面的三元组和一个整数之间存在映射关系,所以JVM解析后只使用方法id?
  • 如果是这样,它是否位于符号表中?

谢谢!

4

4 回答 4

7

它是一个指向方法描述符的CONSTANT_NameAndType_info 结构

它几乎由方法名称、参数类型和(有点令人惊讶的)返回类型组成。

于 2012-06-16T04:05:37.780 回答
0

Java 总是通过完全限定的名称来区分其语言元素。

假设您在包中的myMethod(int a, int b)类中有一个方法,那么 java 将使用 name 标识该方法。MyClasscom.mypackagecom.mypackage.MyClass.myMethod(int a , int b)

只是为了让您更深入地了解,当需要解析两个相同的元素时,它还会考虑类加载器。

它确实考虑了哪个类加载器用于加载包含您所引用的方法的特定类。java中有四种类型的类加载器。您可以为此阅读课程文档java.lang.Thread

于 2012-06-16T04:08:40.743 回答
0

我不太了解您要做什么,但我认为仍然有一些可能的答案:

  • 您可能对JNI Method Descriptors感兴趣,这是 JVM(和 JNI 库)内部使用的各种字符串格式之一,用于识别 Java 元素。

  • 很难知道你在说什么。“方法 id”可以是java.lang.reflect.Method对象的引用,也可以是下面提到的方法描述符或任何其他东西。你在哪里读到的?

  • 我怀疑JVM中有这样的表。我的意思是,我怀疑是否存在全局表,因为几乎总是类中检索方法,即使在 JVM 内部处理它时也是如此,因此有理由相信该方法存储在类中。就像我们使用反射来检索方法时一样:

    Class clazz = String.class;
    Method method = clazz.getDeclaredMethod("charAt", Integer.TYPE);
    System.out.println(method.getName());
    

请注意,我向类询问String方法,而不是要求某些 util 类给我方法charAt,它接收一个intand 来自 class String

换句话说,您的标识元组几乎是正确的 - 它只是没有类:

(methodName, methodParameters)

并且,不是从传递类、方法名称和参数类型的 JVM 中检索方法,而是直接从类中检索方法,为类提供方法名称和参数类型。一个微妙的区别,当然,但我认为这是你想知道的。

即使在我下面提到的 JNI 描述符中,这一点也很明显。例如,方法

long f(int i, Class c);

由以下描述符表示:

"(ILjava/lang/Class;)J"

请注意,没有对方法的类的引用。

关于类文件格式的优秀文档(@Lawence 已经指出)可能会给您一些见解。我建议你完整地阅读它。

于 2012-06-16T04:23:39.000 回答
0

1)如何在内部更有效地识别方法?

对内做什么?有许多地方可能需要在“内部”“识别”方法。在字节码编译器中,JIT 编译器、类加载器/链接器、类文件表示、反射 API、调试器等等。他们每个人都有不同的效率问题。

2)我听说过“方法ID”。是不是意味着上面的三元组和一个整数之间存在映射关系,所以JVM解析后只使用方法id?

方法 id 用于类文件表示,并且可以被任何基于它的东西使用,包括类加载器/链接器、JIT 编译器和调试器。

JVM 不解析 Java 代码。

3)如果是这样,它是否驻留在符号表中?

它可能会。这取决于“符号表”的含义。请记住,在类的整个生命周期中,有很多地方需要方法识别。例如,Java 反射 API 需要方法信息来实现方法,getDeclaredMethod(...)例如Method.

于 2012-06-16T04:35:01.713 回答