简体   繁体   English

Java 编译与 Perl 编译

[英]Java Compilation vs Perl Compilation

How different is the compilation procees of Java and Perl ? Java 和 Perl 的编译过程有何不同? Both produce a byte code but what happens after that?两者都产生一个字节码,但之后会发生什么? Is the interpretation in perl and conversion from object code to machine code in java is all that is different? perl 中的解释和 java 中从目标代码到机器代码的转换是否完全不同? If so then why cant Java be a scripting language?如果是这样,那么为什么 Java 不能成为脚本语言?

There is no definitive answer to this question but I will try anyway.这个问题没有明确的答案,但无论如何我都会尝试。

Java can compile code more aggressively, as it is not as dynamic as Perl. Java 可以更积极地编译代码,因为它不像 Perl 那样动态。 What makes Java unsuitable as a scripting language is that Java 不适合作为脚本语言的原因是

  • you have to write quite a bit of code to do something simple.你必须编写相当多的代码才能做一些简单的事情。 eg "hello world" is 5 lines.例如,“hello world”是 5 行。
  • file and string manipulation is relatively complicated compared to Perl.与 Perl 相比,文件和字符串操作相对复杂。
  • it is hard to run another program from Java.很难从 Java 运行另一个程序。
  • you could use BeanShell or Groovy for scripting Java, but you wouldn't because there is a long list of languages which would be a better choice.您可以使用 BeanShell 或 Groovy 编写 Java 脚本,但您不会,因为有一长串语言是更好的选择。 eg bash for a start.例如 bash 开始。

Java and Perl are languages that are not per se compiled or interpreted, but both have only one main implementation. Java 和 Perl 本身不是编译或解释的语言,但两者都只有一个主要实现。

Java爪哇

Java source code is compiled ahead-of-time to a portable bytecode. Java 源代码提前编译为可移植的字节码。 Some optimizations are applied in this step.在此步骤中应用了一些优化。 This byte code is then executed by the JVM, either by interpretation or by JIT compilation, at the choice of the JVM.该字节码随后由 JVM 执行,通过解释或 JIT 编译,由 JVM 选择。 There is nothing inherent in the language that would prevent compilation + execution in a single step.该语言中没有任何内在的东西会阻止编译 + 执行。

Perl珀尔

In the perl interpreter, the VM and compiler are tightly integrated.在 perl 解释器中,VM 和编译器是紧密集成的。 Even during parsing of the source code, certain parts may already be executed.即使在解析源代码期间,某些部分也可能已经执行。 Each executable unit produces an “Opcode Tree” which has both the roles of an AST and of bytecode.每个可执行单元产生一个“操作码树”,它同时具有 AST 和字节码的作用。 This incremental compilation means that it is not possible to really separate compilation from execution, although it would be sometimes possible to cache the compiled result, or to JIT part of the optree.这种增量编译意味着不可能真正将编译与执行分开,尽管有时可以缓存编译结果,或缓存到 optree 的 JIT 部分。 The opcodes are then interpreted.然后解释操作码。

Comparison比较

Perl compiles much faster than Java, but only very few optimizations are applied, eg constant folding or removal of unnecessary opcodes. Perl 的编译速度比 Java 快得多,但只应用了很少的优化,例如常量折叠或删除不必要的操作码。 More complex optimizations are too expensive for scripting usage.更复杂的优化对于脚本使用来说太昂贵了。 The lack of JIT support and advanced optimizations also means that Perl is usually much slower than Java.缺乏 JIT 支持和高级优化也意味着 Perl 通常比 Java 慢得多。

In principle, both VMs (JVM and perl) can be used for other languages as well.原则上,两个 VM(JVM 和 perl)也可用于其他语言。 The lack of a formal specification and the very Perl-centric implementation means that no other languages use the perl interpreter as a VM, whereas many languages can compile to JVM bytecode (examples include languages like Python, Ruby, Perl6, Clojure, …).缺乏正式规范和以 Perl 为中心的实现意味着没有其他语言将 perl 解释器用作 VM,而许多语言可以编译为 JVM 字节码(示例包括 Python、Ruby、Perl6、Clojure 等语言)。

However, the JVM is optimized for long-running programs like server software or desktop applications.但是,JVM 针对服务器软件或桌面应用程序等长时间运行的程序进行了优化。 This makes it a feasible tradeoff to perform costly optimizations.这使得执行代价高昂的优化成为一种可行的权衡。 OTOH Perl is not only used for large programs but also small tools where start-up cost is important. OTOH Perl 不仅用于大型程序,还用于启动成本很重要的小型工具。 Therefore simple Perl scripts may only need as little as 2 MB of memory, and can execute faster than the JVM needs for startup alone.因此,简单的 Perl 脚本可能只需要 2 MB 的内存,并且可以比 JVM 单独启动所需的速度更快。 While the JVM can be used for scripting, the startup cost and extreme memory usage often makes it unattractive.虽然 JVM用于编写脚本,但启动成本和极端内存使用量通常使其缺乏吸引力。

Terminology note: scripting is executing a program without manually compiling it.术语说明:脚本是在不手动编译的情况下执行程序。 This has nothing to do with interpreted vs. compiled.这与解释与编译无关。 In Unix, the shebang can be used to specify the interpreter of a script.在 Unix 中, shebang可用于指定脚本的解释器。

The first thing to note is that the "compilation processes" are not inherent to the respective languages.首先要注意的是,“编译过程”不是各自语言所固有的。 Rather they are aspects of specific implementations of the respective language.相反,它们是相应语言的特定实现的方面。 (Even Java bytecodes, the JVM, and related stuff are implementation details ... and not universal to all implementations of the Java language.) (即使是 Java 字节码、JVM 和相关的东西也是实现细节……并不是所有 Java 语言的实现都通用。)

The "what happens next" after compilation to bytecodes is ... implementation dependent.编译为字节码后的“接下来会发生什么”是……依赖于实现。

  • For Java, the bytecodes are typically interpreted for a bit (to gather some stats) and then compiler to native code.对于 Java,字节码通常会被解释一点(以收集一些统计信息),然后编译为本机代码。 But not always;但不总是; eg look up the java -int command option.例如查找java -int命令选项。 And technically speaking, there isn't even a requirement to have bytecodes anywhere in the picture.从技术上讲,甚至不需要在图片的任何地方都有字节码。 (Though there are legal issues about use of the trademark "Java" ...) (虽然使用商标“Java”存在法律问题......)

  • For Perl, my understanding is that the bytecodes are typically just interpreted.对于 Perl,我的理解是字节码通常只是被解释。 But the other wrinkles are that Perl compilers can generate other forms of code, and that Perl can directly interpret the "internal form" the Perl compiler front-end produces.但其他问题是 Perl 编译器可以生成其他形式的代码,并且 Perl 可以直接解释 Perl 编译器前端生成的“内部形式”。

So to answer your questions:所以回答你的问题:

How different are the compilation processes of Java and Perl? Java 和 Perl 的编译过程有何不同?

See above.看上面。 In both cases it is more complicated than you portray.在这两种情况下,它都比您描述的要复杂。

Both produce a byte code ...两者都产生一个字节码......

Again, not necessarily true.同样,不一定正确。

... but what happens after that? ……但是在那之后会发生什么? Is the interpretation in perl and conversion from object code to machine code in java is all that is different? perl 中的解释和 java 中从目标代码到机器代码的转换是否完全不同?

Well the "bytecode" instruction sets will necessarily be different, because of the nature of the respective "virtual machines".由于各自“虚拟机”的性质,“字节码”指令集必然会有所不同。 The JVM is an essentially statically typed thing where the formal type of each and every variable and expression is known ... ane either a primitive or some kind of object type. JVM 本质上是一种静态类型的东西,其中每个变量和表达式的形式类型都是已知的……可以是原始类型或某种对象类型。 By contrast, the Perl VM needs to be (more) dynamically typed because of the nature of the Perl language.相比之下,由于 Perl 语言的性质,Perl VM 需要(更多)动态类型化。

If so then why cant Java be a scripting language?如果是这样,那么为什么 Java 不能成为脚本语言?

Well clearly, the "if so" part is not satisfied ... there are significant differences.很明显,“如果是这样”部分不满足......存在显着差异。

But (IMO) there are stronger reasons why Java would not be a good scripting language:但是(IMO)Java 不是一个好的脚本语言有更充分的理由:

  • Java is relatively verbose Java相对冗长
  • Java insists that types and variables be declared Java 坚持声明类型和变量
  • Java is essentially statically type checked Java本质上是静态类型检查的
  • Java's support for functional style programming (eg first-class and higher order functions) has traditionally been poor (though this is improving ...) Java 对函数式编程(例如一等和高阶函数)的支持传统上很差(尽管这正在改进......)
  • Java has limited ability to extend the language core (like typical scripting languages can do) Java 扩展语言核心的能力有限(就像典型的脚本语言一样)
  • The startup time for a (typical) JVM is significantly longer than for regular scripting languages. (典型)JVM 的启动时间比常规脚本语言要长得多。

These things all combine to make Java a poor choice for scripting 1, 2 .这些因素结合在一起使 Java 成为编写脚本的糟糕选择1, 2 But the flip-side is that they make Java a good choice for situations that require higher performance and the improved reliability of static, compile-time typing.但另一方面,它们使 Java 成为需要更高性能和提高静态编译时类型可靠性的情况的不错选择。

(In a sense, the use of bytecodes and the nature of the compilation process are largely immaterial to scripting versus non-scripting ... provided that compilation isn't too slow ... at the wrong time.) (从某种意义上说,字节码的使用和编译过程的性质对于脚本与非脚本而言在很大程度上无关紧要......前提是编译不太慢......在错误的时间。)


1 - The Java 9 release introduced the "jshell" command which allows you to run Java interactively. 1 - Java 9 版本引入了“jshell”命令,它允许您以交互方式运行 Java。 Unfortunately, it is not really suitable for scripting because "jshell" scripts cannot access the command line arguments.不幸的是,它并不真正适合脚本编写,因为“jshell”脚本无法访问命令行参数。

2 - The Java 11 release allows you compile and run a single Java source file in one command like this: java SomeCommand.java . 2 - Java 11 版本允许您使用如下命令编译和运行单个 Java 源文件: java SomeCommand.java This still has the problem of JVM slow startup, with the addition overheads of a source to bytecode compilation step.这仍然存在 JVM 启动缓慢的问题,以及字节码编译步骤源的额外开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM