V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lbllol365
V2EX  ›  Java

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

  •  
  •   lbllol365 · 2020-03-09 13:17:24 +08:00 · 3957 次点击
    这是一个创建于 1719 天前的主题,其中的信息可能已经有所发展或是发生改变。
    各位前辈好,没毕业小菜鸟在看《深入理解 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 ?

    懂的前辈点一个关键点就可以了,我自己去查资料就好。谢谢!
    第 1 条附言  ·  2020-03-09 13:50:36 +08:00
    问题应该是“C++如何编译为 JVM 字节码,然后跑在 JVM 上”

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

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

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

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

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

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

    PS:java 本身就能通过接口实现多继承。
    ipwx
        16
    ipwx  
       2020-03-09 14:02:07 +08:00
    > PS:java 本身就能通过接口实现多继承。

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

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

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

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

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

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