`
RednaxelaFX
  • 浏览: 3052483 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

答复: 通过代码简单介绍JDK 7的MethodHandle,并与.NET的委托对比(二)

    博客分类:
  • Java
阅读更多
原帖地址:http://www.iteye.com/topic/477934?page=3#1186622
再顺手转回来免得以后找起来麻烦

star022 写道
Java代码
findStatic(  
    TestMethodHandle1.class, // 方法所属类型(Class)  
    "hello",                 // 方法名  
    type                     // 由参数和返回值类型组成的“方法类型”  
); 

type// 由参数和返回值类型组成的“方法类型”
“方法类型”这个参数设计得很失败,
一个类中的方法,如果方法名和参数个数及类型一样,这个类能正确编译吗?
其实MethodHandle最终只需要暴露类似这样一个静态方法即可:
//方法如果没有返回值,为void
MethodHandle.<T>invoke(
    Class clazz, // 方法所属类型(Class)  
     String methodName, // 方法名  
     Object... params//方法参数,可以运行时确定参数个数及类型,定位到具体方法
)


你的思路被局限在Java“语言”里了。JSR 292的主要服务对象是JVM上的动态语言,而不是Java。如果你了解JVM的spec而不只是Java的spec,你应该能理解Java字节码不是只能通过Java编译器来生成的。你可以把我之前回帖的那段完整引用一次:
RednaxelaFX 写道
star022 写道
定位到一个java方法,其实只需要类型(Class),方法名及参数即可。

对,说得一点也没错,所以MethodHandles的API就是这样的:
引用
findStatic(
    TestMethodHandle1.class, // 方法所属类型(Class)
    "hello",                 // 方法名
    type                     // 由参数和返回值类型组成的“方法类型”
);

如果只是要做Java的method overload resolution,当然只要参数类型不要返回值类型就够了,但了解class文件及JVM内部数据组织方式的话就会知道,方法的签名(signature)在class文件里是以方法描述符(method descriptor)的形式存在,而该描述符上是有返回值类型的。MethodHandles的API这么设计就是为了快,能更直接的访问VM里的信息,以最快的方式找到目标方法。


如果那段文字仍然不能让你明白,那请看下面的例子。
首先要明确的是,在Java语言里,method overload只依赖于方法名和参数类型,不考虑返回值类型;仅在返回值类型不同的方法无法通过Java编译器的编译。
但生成Java字节码的方式有很多:JVM上有非常多其它语言,它们的编译器都可以生成Java字节码;动态代理要生成字节码;再不行,手工生成字节码也是可以的。从JVM的角度看,无论字节码的来源是什么,只要符合class文件规范、只要加载成功,JVM就可以执行那些字节码。
这里我用bitescript来生成一个class文件,类名为TestMethodSameName,包括两个foo方法,它们只在返回值类型上不同:
require 'rubygems'
require 'bitescript'
include BiteScript

fb = FileBuilder.build(__FILE__) do
  public_class 'TestMethodSameName' do
    public_static_method 'foo', void, int do
      ldc 'TestMethodSameName.foo:(I)V'
      aprintln
      returnvoid
    end
    
    public_static_method 'foo', int, int do
      ldc 'TestMethodSameName.foo:(I)I'
      aprintln
      iload 0
      ireturn
    end
    
    public_static_method 'main', void, string[] do
      push_int 123
      invokestatic this, 'foo', [void, int]
      push_int 456
      invokestatic this, 'foo', [int, int]
      pop
      returnvoid
    end
  end
end

fb.generate do |filename, class_builder|
  File.open(filename, 'w') do |file|
    file.write(class_builder.generate)
  end
end

得到的class文件,内容如下:
Compiled from "test5.rb"
public class TestMethodSameName extends java.lang.Object{
public static void foo(int);
  Code:
   0:   ldc     #9; //String TestMethodSameName.foo:(I)V
   2:   getstatic       #15; //Field java/lang/System.out:Ljava/io/PrintStream;
   5:   swap
   6:   invokevirtual   #21; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   9:   return

public static int foo(int);
  Code:
   0:   ldc     #24; //String TestMethodSameName.foo:(I)I
   2:   getstatic       #15; //Field java/lang/System.out:Ljava/io/PrintStream;
   5:   swap
   6:   invokevirtual   #21; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   9:   iload_0
   10:  ireturn

public static void main(java.lang.String[]);
  Code:
   0:   bipush  123
   2:   invokestatic    #28; //Method foo:(I)V
   5:   sipush  456
   8:   invokestatic    #30; //Method foo:(I)I
   11:  pop
   12:  return

}

如果用Java语法来写,就是:
public class TestMethodSameName {
    public static void foo(int i) {
        System.out.println("TestMethodSameName.foo:(I)V");
    }

    public static int foo(int i) {
        System.out.println("TestMethodSameName.foo:(I)I");
        return i;
    }

    public static void main(String[] args) {
        foo(123); // foo:(I)V
        foo(456); // foo:(I)I
    }
}

再次注意到这段代码用Java编译器确实编译不了。但上面生成的字节码对JVM来说却是完全没问题的。执行结果输出如下:
引用
TestMethodSameName.foo:(I)V
TestMethodSameName.foo:(I)I

这很好的说明了在深入到底层去挖掘MethodHandle时,指定返回值类型的必要性。
JDK原本包含的普通反射API之所以不需要指定返回值类型是因为它只是为Java语言服务的。如今的JSR 292则是为JVM上所有语言服务,主要目标是各种动态语言,但也不拒绝Java去使用它。

关于bitescript的用法,请参考这一帖的例子。上面生成的class文件我也放在附件里了,不相信例子的输出结果的话请自己执行一下,眼见为实。
分享到:
评论
3 楼 phyeas 2009-10-01  
  原来是第6章。。
2 楼 RednaxelaFX 2009-10-01  
phyeas 写道
  好像是inside jvm第3章还是第4章的内容,还好看过,不至于太OUT 

《Inside the Java Virtual Machine》第二版的6.3.3讲解了描述符,6.6讲解了方法。在6.6的第一段就提到了仅靠返回值也可以区分方法的情况。
1 楼 phyeas 2009-10-01  
  好像是inside jvm第3章还是第4章的内容,还好看过,不至于太OUT 

相关推荐

    JDK7源代码

    《深入解析JDK7源代码》 JDK7(Java Development Kit 7)是Java编程语言的一个重要版本,它的源代码对于理解Java平台的工作原理、学习面向对象编程以及提升编程技巧具有极大的价值。在这个资源中,包含了 javax、...

    Java 7.0 JDK 7 API CHM part02

    Java 7.0 JDK 7 API CHM part02 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part03

    Java 7.0 JDK 7 API CHM part03 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part05

    Java 7.0 JDK 7 API CHM part05 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part01

    Java 7.0 JDK 7 API CHM part01 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part04

    Java 7.0 JDK 7 API CHM part04 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    jdk7源代码

    Java Development Kit(JDK)是Java编程语言的核心组件,提供了编写、编译、调试和运行Java应用程序所需的...对比JDK 7与更高版本的源代码,可以帮助开发者追踪语言的发展,理解新特性的实现原理,从而提升编程能力。

    Java帮助文档 JDK全系列 官方中英下载地址.docx

    JDK是由Sun Microsystems(现已被Oracle公司收购)开发并维护的,自Java诞生以来,它一直是Java开发者的首选SDK。本文将深入探讨JDK的主要组件、功能及其不同版本的下载链接。 1. JDK的主要组件: - **javac**:...

    jdk-7u191 (windows和linux)

    标题提到的"jdk-7u191"指的是JDK的第7个主要版本的第191次更新。此版本在发布时是一个重要的里程碑,因为Java 7引入了许多新特性,如动态类型、字符串inswitch、try-with-resources语句等,极大地提高了开发效率。 ...

    jdk1.6 tools.jar

    总的来说,了解并掌握tools.jar在JDK中的作用,有助于我们更好地理解和维护Java开发环境,提高开发效率。遇到问题时,通过正确诊断和处理,可以确保开发工具的正常运行,进而保证软件开发流程的顺利进行。

    javajdk8源码-open-jdk:open-jdk源码jdk7:http://download.java.net/openjdk/jdk

    OpenJDK 8是基于Java SE 8规范的开源实现,它与Oracle JDK 8在功能上非常接近,但OpenJDK是免费且无版权限制的,而Oracle JDK则包含一些闭源的特性和服务。 在OpenJDK 7和8中,有一些重要的新特性和改进: 1. **...

    jdk1.7.0_79下载jdk-7u79-windows-x64

    **Java Development Kit (JDK) 1.7.0_79详解** JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的重要工具集。本文将深入探讨JDK 1.7.0_79版本,该版本特别针对Windows x64操作系统进行...

    jdk-7-windows-x32

    **Java Development Kit (JDK) 7 for Windows 32位详解** JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的核心工具集。JDK 7,也称为Java SE 7 (Java Standard Edition 7),是Java语言...

    Jdk7绿色版

    虽然描述中没有明确指出Jdk7绿色版包含MySQL,但是提到了“使用”,这可能意味着该版本提供了一种简便的方法来与MySQL配合,可能是通过预配置的连接驱动或其他工具。 关于JDK7的重要知识点: 1. **多线程改进**:...

    jsf-ri.jar from https://javaserverfaces.dev.java.net/

    https://javaserverfaces.dev.java.net/ mojarra-1.2._11_b0_FCS JDK 1.5 绝对能用 good luck

    JDK7安装包wins.zip

    JDK7,全称为Java SE 7 (Java Platform, Standard Edition 7),是Java平台的一个重大更新,于2011年发布,引入了许多新特性和改进,提升了开发者的工作效率和程序性能。"JDK7win安装版"表明这是专门为Windows操作...

    Java JDK 7学习笔记 PDF

    Java JDK 7是Java开发工具包的一个重要版本,它的全称是Java Development Kit,是用于构建和运行Java应用程序的关键组件。...通过这份PDF学习笔记,读者将能深入理解JDK 7的新特性,并能将其应用到实际项目中。

    jdk-7u80-windows-x64.exe 【官方下载的jdk1.7、jdk7,windows 64位版】

    1. **多语言支持**:Java 7增加了对其他编程语言的支持,如Groovy、Scala等,通过JEP(JDK Enhancement Proposals)292,使得这些语言可以在Java虚拟机(JVM)上运行。 2. **try-with-resources**:这是一个语法糖...

    jdk1.7 64位官方正式版 jdk-7u76-linux-x64.tar.gz

    Java Development Kit (JDK) 1.7 64位官方正式版,即`jdk-7u76-linux-x64.tar.gz`,是Oracle公司为Linux 64位操作系统提供的Java开发工具集。这个版本的JDK对于开发和运行基于Java技术的应用程序至关重要,特别是当...

Global site tag (gtag.js) - Google Analytics