lbllol365
V2EX  ›  Java

请问 C++这种支持多继承的语言是怎么跑在 JVM 上的?

  •  
  •   lbllol365 · Mar 9, 2020 · 4463 views
    This topic created in 2278 days ago, the information mentioned may be changed or developed.
    各位前辈好,没毕业小菜鸟在看《深入理解 Java 虚拟机》时有一个如题的疑惑,想请教大家。

    是这样的:我在看到第六章 类文件结构时,看到“super_class (父类索引)”这个字段,书上说“由于 Java 语言不允许多继承,所以父类索引只有一个”。我联想到 JVM 是语言无关的,所以我当时觉得 JVM 应该会支持多个父类索引吧。然后我去查了 Java SE 8 的 JVM 规范,里面说 super_class 这个索引指向一个“ CONSTANT_Class_info”结构,然后我看这个结构是代表一个类或者接口( The CONSTANT_Class_info structure is used to represent a class or an interface )。那么这样是不是可以认为 JVM 在“super_class"这一字段上不支持多继承?然而我们又知道 C++是可以跑在 JVM 上的? But how ?

    懂的前辈点一个关键点就可以了,我自己去查资料就好。谢谢!
    Supplement 1  ·  Mar 9, 2020
    问题应该是“C++如何编译为 JVM 字节码,然后跑在 JVM 上”

    我知道,这个东西在工程上很扯,完全没必要。我只是因为 JVM 声称“语言无关性”,所以想探究这种可能。
    Supplement 2  ·  Mar 9, 2020
    我在用必应搜索这个问题时,看到的知乎里一条类似的问题。

    https://www.zhihu.com/question/51380338
    31 replies    2020-03-10 20:31:16 +08:00
    tabris17
        1
    tabris17  
       Mar 9, 2020
    把 C++代码编译成 JVM 的字节码,不需要用到类结构都是可以的
    jinsongzhao
        2
    jinsongzhao  
       Mar 9, 2020
    jni 接口调用动态连接库实现调用 C++库的吧,这种模式不算跑在 JVM 上,是使用本地 CPU 指令运行了。
    参见: https://www.cnblogs.com/sunseine/p/3964828.html
    lbllol365
        3
    lbllol365  
    OP
       Mar 9, 2020
    @tabris17 不需要强制遵守 class 文件格式和语法吗?还是“类结构”不属于 class 文件强制要求的内容?这个我去查一下。
    lbllol365
        4
    lbllol365  
    OP
       Mar 9, 2020
    @jinsongzhao 这种情况我了解的。要是直接编译成 JVM 字节码呢
    augustheart
        5
    augustheart  
       Mar 9, 2020
    什么叫做 c++跑在 jvm 上?
    jvm 上面跑的也不是 java,而是 java 字节码。
    BrettD
        6
    BrettD  
       Mar 9, 2020 via iPhone
    C++不是直接编译成目标架构二进制机器码吗,怎么运行在 JVM 上呢?
    augustheart
        7
    augustheart  
       Mar 9, 2020
    @BrettD 虽然没人做这种无聊东西,不过理论上 c++编译成 java bytecode 也是可以的吧……
    augustheart
        8
    augustheart  
       Mar 9, 2020
    @BrettD llvm 不熟,不知道有没有做过这事
    lbllol365
        9
    lbllol365  
    OP
       Mar 9, 2020
    @augustheart 嗯,确实说的不清楚,应该是“C++编译为 JVM 字节码,跑在 JVM 上”。感谢提醒
    lbllol365
        10
    lbllol365  
    OP
       Mar 9, 2020
    @BrettD C++编译为 JVM 字节码,跑在 JVM 上。虽然在工程上很扯,但是 JVM 不是声称“语言无关性”吗,所以想探究这种可能。
    ipwx
        11
    ipwx  
       Mar 9, 2020
    首先,我没见过 C++ target JVM 的编译器。

    不过就算 JVM 本身没支持多继承,你在转义过程中加点料不就能支持了。反正 C++ 那种多继承,RTTI 弱到爆炸,只要编译器足够牛逼,什么都能模拟。
    augustheart
        12
    augustheart  
       Mar 9, 2020
    @lbllol365 虽然我不熟悉 java 这块,不知道有哪个项目把 c++编译成 java 字节码,但是假如真的有这么一个项目,只要它是真的支持 jvm,那么它的 target 就是 jvm,和 target 是 linux、windows 之类的一回事。生成对应平台的目标就要支持对应平台的规范。
    回到你的困惑,与 jvm 的语法也不等于 java 的语法一样,机器码 /汇编的语法和 c++的语法也不是一回事。语言层的概念在最终目标里面完全是另外一回事。
    lbllol365
        13
    lbllol365  
    OP
       Mar 9, 2020
    @ipwx 我是在用必应搜索这个问题时,看到了知乎的这个问题 https://www.zhihu.com/question/51380338

    嗯,我再去查一下
    augustheart
        14
    augustheart  
       Mar 9, 2020
    另外这个事可以参考一下 java 那个没有血缘关系的亲兄弟 c#扩展一下思考。c++/clr 就是整个把.net 与机器码混合在一起跑了。
    az467
        15
    az467  
       Mar 9, 2020
    >我们又知道 C++是可以跑在 JVM 上的

    反正我不知道 = =,我只知道出现过几个 c2j 转换器,不过貌似理论上是可以的。
    JVM 的底层结构又不影响顶层语言怎么实现,用别的办法去模拟就好了(比如增加一个 list 属性)。

    你非要深究的话,Python 支持多继承,你可以查查看 Jython 是怎么实现的。

    PS:java 本身就能通过接口实现多继承。
    ipwx
        16
    ipwx  
       Mar 9, 2020
    > PS:java 本身就能通过接口实现多继承。

    www 其实 Scala 也有 trait,模拟多继承,一般情况下够用了。
    lbllol365
        17
    lbllol365  
    OP
       Mar 9, 2020
    @augustheart 行,我去看一下
    ipwx
        18
    ipwx  
       Mar 9, 2020
    看了楼主的新的追加,我觉得大可以用一句话高屋建瓴,解决楼主的一切疑惑:

    “图灵完全的任何 computing machine 都是等价的。”

    JVM 是图灵完全的,C++ 是图灵完全的。所以它们都可以互相表达,只是效率高低、以及实现细节的繁易问题罢了。

    至于 Open Source Project ?我没见过实用的。如果说要看 toy project,那随便搜,肯定有。
    lbllol365
        19
    lbllol365  
    OP
       Mar 9, 2020
    我还是看得东西少啊,太菜了,谢谢各位了,自闭学习了......
    augustheart
        20
    augustheart  
       Mar 9, 2020
    @lbllol365 老实说,可能你会越看越糊涂,我说完就后悔了,因为研究 clr 就扯远了……
    你先回顾一下编译的具体过程。把 c++解析为语法树。然后从语法树产生 ir,在 ir 这个阶段它就是平台无关了。也就是说,接下来就是从 ir 转换到 jvm 字节码了。
    然后需要考虑的就是 ir 怎么对应到 jvm,但是从我这个半桶水 c++er 来看,这个可能只是个苦力活。
    当然,实际写一个这种东西的困难还有包括 java 的标准库的调用。这个就真的可以参考 c++/clr 了。
    lbllol365
        21
    lbllol365  
    OP
       Mar 9, 2020
    @augustheart 前辈说得很有道理,我可能就是忽视了编译的本质,感谢!
    CismonX
        22
    CismonX  
       Mar 9, 2020
    Java Bytecode 作为 IR,如楼主所说,是语言无关的,它不需要关注诸如 C++ 的多继承这类高级语言的特性。因此楼主的问题可以拆开成两个问题:

    1. C++的多继承可以如何实现? 答:可以使用 vtable 实现。

    2. C++如何编译为 Java Bytecode ?答:可以参考 gcc (C++ -> GIMPLE) 和 clang (C++ -> LLVM IR) 等编译器的前端,它们的实现原理都是大同小异的。
    si
        23
    si  
       Mar 9, 2020
    我对 C++和 Java 都不熟,只提供一些想法。
    可以编译的时候把多个父类组合成一个类,然后直接继承这个组合后的类。
    比如 A 继承 B 和 C 两个,把 B 和 C 的代码组合成 D,然后 A 直接继承 D。
    或者根本不用在 class 文件里标明继承关系,不用和 java 一样一个 class 文件表示一个类,
    直接把整个程序编译成一个 class 文件就行,中间进行什么组合拼接都可以,只要程序执行的效果一样的就行了。
    所有程序都是要最终的执行结果,中间有什么变化都没什么关系。
    就像是打开一个网页的时候,也只会关心打开快不快,只要用起来一样,不管后面是 Java 还是 php,都不影响。
    qieqie
        24
    qieqie  
       Mar 9, 2020 via iPhone
    有 Clang,只要上一个 LLVM JVM Backend 就行。
    不过 Hotspot VM 本身都是 c/c++写的,不知道这样套娃的意义何在。
    tabris17
        25
    tabris17  
       Mar 9, 2020
    @lbllol365 C++的类不一定要映射成 JVM 的 class 呀,比如早期 C++编译器就是将 C++翻译成 C 语言再进行编译的
    jinsongzhao
        26
    jinsongzhao  
       Mar 9, 2020
    应该没有这种东西,就算有,也是玩具。C++代码没有 GC 机制,如果要编译出带 GC 功能的,这个编译器一定对代码有要求,比如不允许使用指针等等
    cluulzz
        27
    cluulzz  
       Mar 9, 2020
    cluulzz
        28
    cluulzz  
       Mar 9, 2020
    xcstream
        29
    xcstream  
       Mar 9, 2020
    虽然啥也不懂,但是理论上图灵完备肯定可以。
    Michaelssss
        30
    Michaelssss  
       Mar 9, 2020 via Android
    …都不是同一个语境
    abcbuzhiming
        31
    abcbuzhiming  
       Mar 10, 2020
    C++可以跑在 JVM 上?我孤陋寡闻了,没听说过,如果你说的是指用 jni 调用 C++,那是二进制调用,已经越过了 jvm 了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5652 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 263ms · UTC 06:10 · PVG 14:10 · LAX 23:10 · JFK 02:10
    ♥ Do have faith in what you're doing.