【问题标题】:What is the internal identification of a Java method?Java 方法的内部标识是什么?
【发布时间】:2012-06-19 02:44:10
【问题描述】:

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

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

(className, methodName, methodParameters)

进一步,

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

谢谢!

【问题讨论】:

  • 你的问题太模糊了。您是在谈论识别编译器中的方法吗?在“.class”文件中?在执行程序中?

标签: java function methods symbol-tables symbol-table


【解决方案1】:

这是一个CONSTANT_NameAndType_info Structure 指向method descriptor

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    请注意,我向String 类询问方法,而不是向某个实用程序类提供方法charAt,它接收int 并来自String 类。

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

    (methodName, methodParameters)
    

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

    这在我下面提到的 JNI 描述符中也很明显。比如方法

    long f(int i, Class c);
    

    由以下描述符表示:

    "(ILjava/lang/Class;)J"
    

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

    excellent documentation on the class file format(已由@Lawence 指出)可能会给您一些见解。我建议您完整阅读。

    【讨论】:

    • "我怀疑 JVM 里面有没有这样的表。" JVM 可以定义这样一个表供内部使用,但这样做可能会使类加载器的垃圾收集复杂化。
    【解决方案3】:

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

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

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

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

    JVM 不解析 Java 代码。

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

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

    【讨论】:

      【解决方案4】:

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

      假设您在类MyClass 中有一个方法myMethod(int a, int b),它位于包com.mypackage 中,那么java 将识别名称为com.mypackage.MyClass.myMethod(int a , int b) 的方法。

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

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

      【讨论】:

      • “java中有四种类型的类加载器”是什么意思?
      • JVM 加载的类可以被以下四种类加载器中的任何一种加载: 1) Bootstrap 类加载器 2) 扩展类加载器 3) 系统类加载器 4) 应用类加载器 请看他们有自己的意义。有关详细信息,请参阅以下链接。 javapapers.com/core-java/java-class-loader
      • 嗯,好的。 (4) 不受其他限制,前三个仅通过指定搜索路径的系统属性约定来区分。这与线程或方法查找有什么关系?该方法是基于类的,因此间接依赖于类加载器,但是提到类加载器的一种分类法如何解决原始问题?
      • 为了区分具有相似签名的方法,我们需要完全限定的类名,并且类间接依赖于类加载器。这个问题在 IBM Websphere 6.0.1 上很普遍,如果我们放置两个 jar 包 common-collections.3.2.jar 和 commons.collections.2.0.jar,那么它无法区分这两个 jar 包的 SetUtil 类中的几个方法。在这种情况下,我们需要定义两个 jar 的加载策略。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      相关资源
      最近更新 更多