【问题标题】:Use of a Compiler from Java to Machine Code使用从 Java 到机器码的编译器
【发布时间】:2019-01-06 11:10:43
【问题描述】:

为什么java代码没有被JVM编译成机器码,即使它比JVM运行得更快而且没有JVM?

我是德国 TUM 的一名计算机科学专业的学生。 我知道 java 的优点和缺点以及例如的优点/缺点。 C/C++。

java 语法与 C++ 非常相似(不能说 C,没看过)。 在 java 中,您不会显式使用堆栈。使用 C 编译器编译 java 代码(在修复小的语法差异之后)将只使用堆。 堆上创建的对象也不会被自动释放。

我最近不得不为 java 语法编写一个“编译器”,因此我对解析代码并将其转换为可用的汇编代码有基本的了解。

如果一家公司创建了一个高效的解析器,它可以在 java 代码中找到对象的生命周期,以将这些对象更改为使用 C++ 中的堆栈,那么编译器可以像常规 C++ 一样编译此代码,从而获得更好的性能而不是使用JVM。此外,堆对象将在不再使用后被释放。 (即使您必须手动添加应该释放对象的行,我认为这可能并不难)

我知道我将这个庞大的话题分解为这个小小的解释。我有什么遗漏或者我的想法有什么问题吗?

(我“有被阻止再提问的危险”。请帮助我改变我的话题以更好地适应这个论坛!)

编辑: 我在大学里使用java,在家里用C++做项目。对我来说,差异很小,可以很容易地改变。至少这是我的经验。

【问题讨论】:

  • 在修正了细微的语法差异之后”——这比你想象的要困难得多。 Java 和 C++ 在语法上有一些细微的相似之处,但仅止于此。它们是完全不同的语言。
  • “即使它比 JVM 运行得更快” - 你如何证明这个假设的合理性?
  • 你如何证明这个假设的合理性? 专门为具有特定 ISA 的 cpu 架构编译和优化的代码在大多数情况下会比 JVM 本身运行得更快,这是它的一个主要缺点java及其虚拟机
  • 而且您还考虑了诸如 JIT 编译和潜在的长期优化步骤之类的问题,这些步骤只能执行因为代码在 JVM 中运行?无论如何(即假设 C 代码确实运行得更快),您的问题的答案很可能是:因为这不值得麻烦,而且由于(您自己的)糟糕的实现,您通常会比 JVM 损失更多的性能。跨度>
  • 我对 JIT 了解不多,但 JIT 不是要让脚本语言更快,从而“更接近”提前编译程序的性能吗?是的,大部分性能都是程序员自己损失的,我完全同意。仍然:一个优化的 java 程序将在性能结果上“损失”一个优化的 C++ 程序(当然 C++ 比 java 可以有更多的优化)。在谈论这样的编译器时,我不是在考虑公司工具,而是对每个 Java 程序员都可用的开放编译器。

标签: java c assembly compilation jvm


【解决方案1】:

找到对象生命周期的高效解析器:这是不可能的,除了特殊/简单的情况外,无法统计确定生命周期。

即使您必须手动添加应该释放对象的行,我认为这可能并不难:这就是我们在 C 或 C++ 中所做的,标记 em> 正在调用免费/删除 :-)

垃圾收集器的存在并不是没有意义的,你不能轻易地用魔法替换垃圾收集器。

当没有垃圾收集器时,有一些方法可以帮助自动释放分配的内存,例如使用std::shared_ptrstd::string 也使用内部计数器来了解何时可以释放内部char *。引用计数器的使用很简单,但是引用计数必须不溢出计数器,当你有一个圆圈时,这种方式不起作用,因为计数器不能降到 0,再次没有魔法

【讨论】:

  • 这是不可能的:我不知道。这是我的一个假设。如果您考虑一下:方法本地的对象可以直接更改为使用堆栈。当然还有更复杂的场景。这就是为什么我添加了 “即使您必须手动添加应该释放对象的行,我认为这可能并不难” 我知道这正是 C/C++ 中所做的事情,但事实并非如此难的。一个简单的想法:添加一个简单的关键字来标记不再使用对象的位置(甚至显式调用 foo = null.
  • 指针实际上是一种选择,但这会增加内存使用量,这在许多情况下都是“坏”的。
  • @MarcoZielbauer:“方法本地的对象可以直接更改为使用堆栈”。这是可能的,但你从中获得了什么?堆栈与堆内存位于相同的 RAM 芯片中,因此没有性能差异。如果程序员告诉它这样做,C++ 编译器会将对象放在堆栈上,主要是因为程序员告诉它这样做。但是由于堆上的 C++ 对象需要显式的delete 操作,它们确实比堆栈对象更昂贵。但在 Java 中,对象不需要delete 操作,因此不受此问题的影响。
  • 编译成汇编代码时会产生影响。正如您所说,堆对象确实比堆栈对象更昂贵。在java中它没有什么区别是的。但是 GC 必须关心这些对象 -> 垃圾收集时间增加。
  • @MarcoZielbauer 这不是垃圾收集器的工作方式。垃圾收集的成本取决于仍然活着的对象的数量,因为这些是必须处理的对象。解除分配的成本完全为零,因为根本不会发生解除分配。当然,当您尝试将代码转换为没有垃圾收集器的东西时,您正在引入可以通过识别纯本地对象来减轻的成本,但是您正在解决刚刚引入的问题,因此这样做仍然没有优势转变。
猜你喜欢
  • 2012-01-15
  • 2015-09-16
  • 1970-01-01
  • 2013-09-22
  • 2016-05-04
  • 2012-08-20
  • 1970-01-01
  • 2019-03-24
  • 2013-09-14
相关资源
最近更新 更多