最近碰到了一个由于java方法的二进制签名导致的问题,促使我去研究了一下java方法的二进制签名,下面就来和大家一起分享。

我在程序中使用了jdom.jar,调用大概方式如下:
    Element a = new Element();
    Element b = new Element();
    a.addContent(b);

程序的编译环境用的是jdom的beta9版本,而运行环境用的是beta10版本。结果就报以下错误:
    java.lang.NoSuchMethodError: org.jdom.Element.addContent(Lorg/jdom/Element;)Lorg/jdom/Element;
    
后来查看原因,发现在beta9中,addContent方法的定义如下:
    Element.addContent(Element x)

而在beta10中,Element改成了Content的子类,并把原来的addContent改为:
    Element.addContent(Content x)

虽然beta10是向下兼容beta9的(即使用beta9的程序可以平滑的迁移到beta10), 但确无法实现代码的二进制兼容,即基于beta9编译的程序能在beta10的环境下使用,或者反之。

究其原因,是因为java是动态绑定的(c++中的分静态绑定和动态绑定),它在运行时才根据方法的二进制签名查找最终调用的方法。在上面的例子中,基于beta9编辑的类中,其调用的方法签名就是(Lorg/jdom/Element;)Lorg/jdom/Element, 而beta10环境下并没有符合该签名的addContent方法,自然就导致的java.lang.NoSuchMethodError。


知道了原因,下面我们就来了解一下java方法的二进制签名。java方法的签名有两部分组成,就是我们熟知的形参和返回值。但在报错或者其他输出情况下,其显示方式比较特别。比如下面的方法:
    Element Element.addContent(Element x)

其二进制签名显示成:
    (Lorg/jdom/Element;)Lorg/jdom/Element

这里,对象被表示成L开始,;结尾的标识,中间是类名。对于基础类型,则按如下显示:
        Type     Chararacter
        boolean      Z
        byte             B
        char            C
        double       D
        float            F
        int               I
        long           J
        object        L
        short         S
        void           V
        array          [
        
        


    


1条评论

  1. 我在 WINDOWS 环境下没什么问题

    到了 LINUX 下就出现了上面的问题

    急!!!!!!!!!!!!!!

发表评论

评论也有版权!