众所周知,在Java中,方法名不足以区分不同的方法。
我认为(可能是错误的),要区分一个方法,它需要以下信息:
(className, methodName, methodParameters)
更远,
- 如何在内部更有效地识别方法?
- 我听说过“方法ID”。是不是意味着上面的三元组和一个整数之间存在映射关系,所以JVM解析后只使用方法id?
- 如果是这样,它是否位于符号表中?
谢谢!
众所周知,在Java中,方法名不足以区分不同的方法。
我认为(可能是错误的),要区分一个方法,它需要以下信息:
(className, methodName, methodParameters)
更远,
谢谢!
它是一个指向方法描述符的CONSTANT_NameAndType_info 结构。
它几乎由方法名称、参数类型和(有点令人惊讶的)返回类型组成。
Java 总是通过完全限定的名称来区分其语言元素。
假设您在包中的myMethod(int a, int b)
类中有一个方法,那么 java 将使用 name 标识该方法。MyClass
com.mypackage
com.mypackage.MyClass.myMethod(int a , int b)
只是为了让您更深入地了解,当需要解析两个相同的元素时,它还会考虑类加载器。
它确实考虑了哪个类加载器用于加载包含您所引用的方法的特定类。java中有四种类型的类加载器。您可以为此阅读课程文档java.lang.Thread
。
我不太了解您要做什么,但我认为仍然有一些可能的答案:
您可能对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
,它接收一个int
and 来自 class String
。
换句话说,您的标识元组几乎是正确的 - 它只是没有类:
(methodName, methodParameters)
并且,不是从传递类、方法名称和参数类型的 JVM 中检索方法,而是直接从类中检索方法,为类提供方法名称和参数类型。一个微妙的区别,当然,但我认为这是你想知道的。
即使在我下面提到的 JNI 描述符中,这一点也很明显。例如,方法
long f(int i, Class c);
由以下描述符表示:
"(ILjava/lang/Class;)J"
请注意,没有对方法的类的引用。
关于类文件格式的优秀文档(@Lawence 已经指出)可能会给您一些见解。我建议你完整地阅读它。
1)如何在内部更有效地识别方法?
对内做什么?有许多地方可能需要在“内部”“识别”方法。在字节码编译器中,JIT 编译器、类加载器/链接器、类文件表示、反射 API、调试器等等。他们每个人都有不同的效率问题。
2)我听说过“方法ID”。是不是意味着上面的三元组和一个整数之间存在映射关系,所以JVM解析后只使用方法id?
方法 id 用于类文件表示,并且可以被任何基于它的东西使用,包括类加载器/链接器、JIT 编译器和调试器。
JVM 不解析 Java 代码。
3)如果是这样,它是否驻留在符号表中?
它可能会。这取决于“符号表”的含义。请记住,在类的整个生命周期中,有很多地方需要方法识别。例如,Java 反射 API 需要方法信息来实现方法,getDeclaredMethod(...)
例如Method
.