Java基础常见面试题总结(上)

基础概念与尝试

Java语言有那些特点

1.简单易学(语法简单,上手容易);

2.面向对象(封装,继承,多态);

3.平台无关性(Java虚拟机实现平台无关性)

4.支持多线程(C++语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而Java语言却提供了多线程支持)

5.可靠性(具备异常处理和自动内存管理机制);

6.安全性(Java语言本身的设计就提供了多重安全防护机制如访问权限修饰符,限制程序直接访问操作系统资源);

7.高效性(通过Just In Time编译器等技术的优化,Java语言的运行效率还是非常不错的)

8.支持网络编程并且很方便;

9.编译与解释并存;

10.............

修正(参见:issue#544):C++11开始(2011年的时候),C++就引入了多线程库,在widows,linux,macos都可以使用std::thread和std::async来创建线程。

参考链接:
http://www.cplusplus.com/reference/thread/thread/?kw=thread

拓展一下:

“Write Once,Run Anywhere(一次编写,随处运行)”这句宣传口号,真心经典,流传了好多年!
以至于,直到今天,依然有很多人觉得跨平台是Java语言最大的优势。
实际上,跨平台已经不是Java最大的卖点了,各种JDK新特性也不是。

目前市面上虚拟化技术已经非常成熟,比如你通过Docker就很容易实现跨平台了。

在我看来,Java强大的生态才是!

Java SE vs Java EE

Java SE(Java Platform,Standard Edition):Java平台标准版,Java编译语言的基础,它包含了支持Java应用程序开发和运行的核心类库以及虚拟机等核心组件。

Java SE可以用于构建桌面应用程序或简单的服务器应用程序。

Java EE(Java Platform,Enterpries Edition):Java平台企业版,建立在Java SE的基础上,包含了支持企业级应用程序开发和部署的标准和规范(比如Servlet,JSP,EJB,JDBC,JPA,JTA,JAavaMail,JMS)。

JavaEE可以用于构建分布式,可移植,健壮,可伸缩和安全的服务端Java应用程序,例如Web应用程序。

简单来说,Java SE是Java的基础版本,Java EE是Java的高级版本。

Java SE更适合开发桌面应用程序或简单的服务器应用程序,JavaEE更适合开发复杂的企业级应用程序或Web应用程序。
除了Java SE和Java EE,还有一个Java ME(Java Platfrom,Micro Edition).

Java ME是Java的微型版本,主要用于开发嵌入式消费电子设备的应用程序,例如手机,PDA,机顶盒,冰箱,空调等。

Java ME无需重点关注,知道有这个东西就好了,现在已经用不上了。

JVM vs JDK vs JRE

JVM

Java虚拟机(Java Virtual Machine,JVM)是运行Java字节码的虚拟机。

JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
字节码和不同系统的JVM实现是Java语言“一次编译,随处可以运行”的关键所在。

如下图所示,不同编程语言(Java,Grovy,Kotiln,JRuby,Clojure...)通过各自的编译器成.class文件,并最终通过JVM在不同平台(Windiws,Mac,Linux)上运行。

 JVM并不是只有一种!
只要满足JVM规范,每个公司,组织或者个人都可以开发自己的专属JVM.

也就是说我们平时接触到的HotSpot VM 仅仅是JVM规范的一张实现而已。

除了我们平时最常用的HotSpot VM外,还有J9VM,Zing VM,JRockit VM等JVM。

维基百科上就有常见JVM的对比:Comparieson of Java virtual machines,感兴趣的可以去看看。

并且,你可以在Java SE Specifications上找到各个版本的JDK对应的JVM规范。

 JDK和JRE

JDK(Java Development Kit)是一个功能齐全的Java开发工具包,供开发者使用,用于创建和编译Java程序。

它包含了JRE(Java Runtime Environment),以及编译器javac和其他工具,如javadoc(文档生成器),jconsole(监控工具),javap(反编译工具)等。

JRE是运行已编译Java程序所需的环境,主要包含以下两个部分:

JVM:也就是我们上面提到的Java虚拟机。

Java基础类库(Class Library):一组标准的类库,提供常用的功能和API(如I/O操作,网络通信,数据结构等)

简单来说,JRE只包含运行Java程序所需的环境和类库,而JDK不仅包含JRE,还包含用于开发和调试Java程序的工具。

如果需要编写,编译Java程序或使用Java API文档,就需要安装JDK.

某些需要Java特性的应用程序(如JSP转换为Servlet或使用反射)也可能需要JDK来编译和运行Java代码。

因此,即使不进行Java开发工作,有时也可能需要安装JDK.

下图清晰展示了JDK,JRE和JVM的关系。

                                                        jdk-include-jre

不过,从JDK9开始,就不需要区分JDK和JRE的关系了,取而代之的是模块系统(JDK被重新组织成94个模块)+Jlink工具(随Java9一起发布的新命令工具,用于生成自定义Java运行时映射,该映像仅包含给定应用程序所需的模块)。

并且,从JDK11开始,Oracle不再单独提供JRE下载。

在Java 9新特性概览这篇文章中,在介绍模块化系统的时候提到:
在引入了模块系统之后,JDK被重新组织成94个模块。

Java应用可以通过新增jlinke工具,创建出只包含所依赖的JDK模块的自定义运行时镜像。

这样可以极大的减少Java运行时环境的大小。

也就是说,可以用jlink根据自己的需求,创建一个更小的runtime(运行时),而不是不管什么应用,都是同样的JRE.

定制的,模块化的Java运行时映像有助于简化Java应用的部署和节省内存并增强安全性和可维护性。

这对于满足现代应用程序架构的需求,如虚拟化,容器化,微服务和云原生开发,是非常重要的。

什么是字节码?

采用字节码的好处是什么?

在Java中,JVM可以理解的代码就叫做字节码(即扩展名.class的文件),它不面向任何特定的处理器,只面向虚拟机。
Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。

所以,Java程序运行时相对来说还是高效的(不过,和C,C=++,Rust,Go等语言还是有一定差距的),而且,由于字节码并不针对一种特定的机器,因此,Java程序无须重新编译便可在多种不同操作系统的计算机上运行。

Java程序从源代码到运行的过程如下图所示:

我们需要格外注意的是.class->机器码这一步。

在这一步JVM类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。

而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了JIT(Just in Time Compilation)编译器,而JIT属于运行时编译。

当JIT编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。
而我们知道,机器码的运行效率肯定是高于Java解释器的。

这也解释了我们为什么经常会说Java是编译与解释共存的语言。

拓展:有关JIT的实现细节:JVMC1,C2编译器

 

                                                                                 Java程序转变为机器代码的过程

HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。

JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。

JDK,JRE,JVM,JIT这四者的关系如下图所示。

 

JDK,JRE,JVM,JIT这四者的关系。

下面这张图是JVM的大致结构模型

                                                                JVM的大致结构模型

为什么说Java语言“编译与解释并存”?

其实这个问题我们将字节码的时候已经提到过,因为比较重要,所以我们这里再提一下。

我们可以将高级编程语言按照程序的执行方式分为两种:
编译型:编译型语言会通过编译器将源代码一次性翻译成科被该平台执行的机器码。

一般情况下,编译语言的执行速度比较快,开发效率比较低,常见的编译性语言有C,C++,Go,Rust等等。

解释型:解释型语言会通过解释器一句一句的将代码解释(interpret)为机器代码后再执行。

解释型语言开发效率比较快,执行速度比较慢。

常见的解释性语言有Python,JavaScript,PHP等等。 

根据维基百科介绍:

为了改善解释语言的效率而发展出的即时编译技术,已经缩小了这两者语言间的差距。这种技术混合了编译语言与解释型语言的优点,它像编译语言一样,先把程序源代码编译成字节码。

到执行期时,再将字节码直译,之后执行。

Java与LLVM是这种技术的代表产物。

相关阅读:基本功|Java即时编译器原理解析及实践

为什么说Java语言“编译与解释并存”?


这是因为Java语言具有编译型语言的特征,也具有解释型语言的特征。

因为Java程序要经过先编译,后解释两个步骤,由Java编写的程序需要先经过编译步骤,生成字节码(.class文件),这种字节码必须由Java解释器来解释执行。

AOT有什么优点?为什么不全部使用AOT呢?

JDK9引入了一种新的编译模式AOT(Ahead of Time Compilation).

和JIT不同的是,这种编译模式会在程序执行前将其编译成机器码,属于静态编译(C,C++,Rust,Go等语言就是静态编译)。

AOT避免了JIT预热等各方面的开销,可以提高Java程序的启动速度,避免预热时间长。

并且,AOT还能减少内存占用和增强Java程序的安全性(AOT编译后的代码不容易被反编译和修改),特别适合云原生场景。

JIT与AOT两这的关键指标对比:

可以看出,AOT的主要优势在于启动时间,内存占用和打包体积。

JIT的主要优势在于具备更高的极限处理能力,可以降

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值