Java为什么解释执行时不直接解释源码?

本文探讨Java源码为何转换为字节码而非直接解释执行的原因。字节码便于虚拟机读取,可跨平台运行,且有助于提高执行速度和安全性。此外,文章还讨论了字节码在内存管理和优化方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://www.zhihu.com/question/34345694

Java源码为什么会经过中间步骤转换为字节码,这样不是增加工作量吗?直接解释源代码一样跨平台。

为什么不在解释运行时直接解释源代码,而是字节码。


  1. 字节码更便于虚拟机读取,不用在解析字符串,所以运行速度比直接解析源代码快。
  2. 语法是会变的,而源代码中没有版本信息,而字节码中不但有版本信息,还可以经由编译过程抹平一些语言层面的变化(即语言语法虽然有变化,但字节码依然遵照原来的规则即可)。
  3. 字节码也可以由其他语言生成,如GroovyClojureScala。需要注意的事,既然这些语言可以编译成字节码,也就可以被Java或其他JVM语言调用。
  • 然而归根到底,没有必须这么设计的绝对理由,很多事物之所以会这样,只是因为被设计成这样。


一切源于更好的设计
1、快
2、跨平台
3、可扩展
4、《the java specification》 和 《 the JVM specification》是分开的,设计之初就承诺支持其他语言编译成字节码,比如 JRuby,scala ,Jython等

CPU从内存或者寄存器中读取数据,而不是直接从硬盘中读取数据!
和这个道理差不多!

为了跨平台,编译成的字节流文件.class,与硬件和操作系统无关,这是跨平台基础,然后具体执行,再用各自平台解释器,解释成本地机器码。另外还有一个安全性的问题,编译的结果本身保证了代码安全和版权。
作者:火雨
链接:http://www.zhihu.com/question/34345694/answer/59501996
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

其实,Java作为一个高级语言,便于开发者阅读和理解代码,jvm虚拟机用于执行代码指令,而指令就不会像源代码那样有很强可读性,另外,class文件内容紧凑,使用空间小,jvm加载类支持从网络加载class文件流,这样可以减少网络带宽,提高性能。
Javac编译过程中,并不是简单的理解为编译成虚拟机能够识别的指令那么简单,在编译过程中,需要对源码进行词法分析,语法分析,语义分析,最后生成字节码。我们都知道Java语言,内存是自动管理的,一个对象实例内存空间的申请、分配和回收都是虚拟机自己去管理的。Java内存分配有动态内存分配,也有静态内存分配,静态内存分配就是在编译时候,就确定需要分配的内存大小,如类的静态常量,对于一些大小不可知的对象,只有运行时才能确定需要申请的空间大小。所以静态分配性能相对动态分配比较高一些。由此看出,Java编译成字节码,除了将源码编译成虚拟机可执行的字节码,也做了一些其他准备工作。
因此,若将源码替代字节码,虚拟机直接执行源码的话,要么程序员将源码写成字节码那样的,这样对程序员不友好,另外就是当虚拟机加载某个类,或者实例化某个对象的时候,虚拟机做一些与编译器类似的工作,但是这样性能会收到很大的影响。
理解的比较浅,可能有很多地方不正确,希望大家一起探讨。

Java9 添加了一个新工具,JShell,然后我下了 ea 版本来尝鲜。应该说从 Java9 开始,Java 就有工具来通过直接解释源码运行程序了(指的是表面上,底层应该还是先生成字节码然后再运行)。
首先写个计算 pi 的程序:
<img src="https://i-blog.csdnimg.cn/blog_migrate/8c28b5f6a01d2bfcf5a14aa0415bbb07.png" data-rawwidth="859" data-rawheight="326" class="origin_image zh-lightbox-thumb" width="859" data-original="https://pic4.zhimg.com/34a2775021ca4db77ac604d6d84a74b3_r.png">
然后用 JShell 来运行:
<img src="https://i-blog.csdnimg.cn/blog_migrate/a181cecb79226e6c2ce395355e8accb8.png" data-rawwidth="409" data-rawheight="46" class="content_image" width="409">是的,你没有看错,以后 Java 居然也可以当脚本语言来用了。当然,比起 Scala 和 Groovy,Java写起来时稍微啰嗦了一点(虽然在这个例子中不是很明显)。不过,这已经很棒了(毕竟这是 Java 嘛 :) ) 是的,你没有看错,以后 Java 居然也可以当脚本语言来用了。当然,比起 Scala 和 Groovy,Java写起来时稍微啰嗦了一点(虽然在这个例子中不是很明显)。不过,这已经很棒了(毕竟这是 Java 嘛 :) )
目前 JShell 的缺点第一在于启动时间较长(JVM的启动时间+JShell自身的启动时间),后期应该会有所改善;第二就是目前内置的方法太少,好吧其实目前只内置了 printf 一个方法...;第三个问题应该是在于Java语言本身,缺少一个 var 关键字(JEP 286 考虑为 Java 添加这一特性,应该有希望在 Java10 中能实现, JEP 286: Local-Variable Type Inference


我就补充点R大的回复。。

Interpreation the source code is OK, but might be slow in many places because of absent of any optimization. By translation, the generate code can be somewhat optimized or simplified.

Norammly, there are a lot of mode for interpretation.
1) Interprete source code directly.
2) Interprete IR, eg. bytecode.
3) between 1) and 2), e.g., interprete AST tree.
4) Translate AST to native code and execute.
5) ..
Many interpreters would mix above four modes. For example, JIT compilation for Java/JavaScript which mixes of bytecode interpretation and native code execution in many projects.

The decison is made for the performance/memory/ factors. For example, the interpreter in CRuby under 1.9 is AST interpreter that does not generate bytecode. However, it generates bytecode since V1.9 for the performance purpose. Similarly, the JRuby+Truffle take the idea of early CRuby. The interpreter walks on the AST tree and then Truffle(Graal) compiles the code and execution. This is also performance purpose.


其实,Java作为一个高级语言,便于开发者阅读和理解代码,jvm虚拟机用于执行代码指令,而指令就不会像源代码那样有很强可读性,另外,class文件内容紧凑,使用空间小,jvm加载类支持从网络加载class文件流,这样可以减少网络带宽,提高性能。
Javac编译过程中,并不是简单的理解为编译成虚拟机能够识别的指令那么简单,在编译过程中,需要对源码进行词法分析,语法分析,语义分析,最后生成字节码。我们都知道Java语言,内存是自动管理的,一个对象实例内存空间的申请、分配和回收都是虚拟机自己去管理的。Java内存分配有动态内存分配,也有静态内存分配,静态内存分配就是在编译时候,就确定需要分配的内存大小,如类的静态常量,对于一些大小不可知的对象,只有运行时才能确定需要申请的空间大小。所以静态分配性能相对动态分配比较高一些。由此看出,Java编译成字节码,除了将源码编译成虚拟机可执行的字节码,也做了一些其他准备工作。
因此,若将源码替代字节码,虚拟机直接执行源码的话,要么程序员将源码写成字节码那样的,这样对程序员不友好,另外就是当虚拟机加载某个类,或者实例化某个对象的时候,虚拟机做一些与编译器类似的工作,但是这样性能会收到很大的影响。
理解的比较浅,可能有很多地方不正确,希望大家一起探讨。


原文







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值