1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?

2024-05-16 01:48

本文主要是介绍1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文为转载,好记性不如烂笔头

1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。

Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

2、Java 代码是怎么运行的?

这个问题可以分三块来回答:

  1. 为什么 Java 要在虚拟机里运行?

  2. Java 虚拟机具体是怎样运行 Java 字节码的?

  3. Java 虚拟机的运行效率究竟是怎么样的?

Java 之所以要在虚拟机中运行,是因为它提供了可移植性。一旦 Java 代码被编译为 Java 字节码,便可以在不同平台上的 Java 虚拟机实现上运行。此外,虚拟机还提供了一个代码托管的环境,代替我们处理部分冗长而且容易出错的事务,例如内存管理。

Java 虚拟机将运行时内存区域划分为五个部分,分别为方法区、堆、PC 寄存器、Java 方法栈和本地方法栈。Java 程序编译而成的 .class 文件,需要先加载至方法区中,方能在 Java 虚拟机中运行。

为了提高运行效率,标准 JDK 中的 HotSpot 虚拟机采用的是一种混合执行的策略。首先,它会解释执行 Java 字节码,然后会将其中反复执行的热点代码,以方法为单位进行即时编译,翻译成机器码后直接运行在底层硬件之上。HotSpot 装载了多个不同的即时编译器,以便在编译时间和生成代码的执行效率之间做取舍。

3、Java 虚拟机是如何加载 Java 类的?

Java 虚拟机将字节流转化为 Java 类的过程,可分为加载、链接以及初始化三大步骤。也可以用盖房子来类比 Java 虚拟机中的类加载。

加载是指查找字节流,并且据此创建类的过程。以盖房子为例,村里的 Tony 要盖个房子,那么按照流程他得先找个建筑师,跟他说想要设计一个房型,比如说“一房、一厅、四卫”。这里的房型相当于类,而建筑师,就相当于类加载器。村里有许多建筑师,他们等级森严,但有着共同的祖师爷,叫启动类加载器(boot class loader)

加载需要借助类加载器,在 Java 虚拟机中,类加载器使用了双亲委派模型,即接收到加载请求时,会先将请求转发给父类加载器。

链接,是指将创建成的类合并至 Java 虚拟机中,使之能够执行的过程。链接还分验证、准备和解析三个阶段。其中,解析阶段为非必须的。

初始化,则是为标记为常量值的字段赋值,以及执行方法的过程。类的初始化仅会被执行一次,这个特性被用来实现单例的延迟初始化。这放在我们盖房子的例子中就是,只有当房子装修过后,Tony 才能真正地住进去。

4、如何监控和诊断 JVM 堆内和堆外内存使用?

了解 JVM 内存的方法有很多,具体能力范围也有区别,简单总结如下:

可以使用综合性的图形化工具,如 JConsole、VisualVM(注意,从 Oracle JDK 9 开始,VisualVM 已经不再包含在 JDK 安装包中)等。这些工具具体使用起来相对比较直观,直接连接到 Java 进程,然后就可以在图形化界面里掌握内存使用情况。以 JConsole 为例,其内存页面可以显示常见的堆内存和各种堆外部分使用状态。

也可以使用命令行工具进行运行时查询,如 jstat 和 jmap 等工具都提供了一些选项,可以查看堆、方法区等使用数据。

或者,也可以使用 jmap 等提供的命令,生成堆转储(Heap Dump)文件,然后利用 jhat 或 Eclipse MAT 等堆转储分析工具进行详细分析。

如果你使用的是 Tomcat、Weblogic 等 Java EE 服务器,这些服务器同样提供了内存管理相关的功能。

另外,从某种程度上来说,GC 日志等输出,同样包含着丰富的信息。

这里有一个相对特殊的部分,就是是堆外内存中的直接内存,前面的工具基本不适用,可以使用 JDK 自带的 Native Memory Tracking(NMT)特性,它会从 JVM 本地内存分配的角度进行解读。

5、JVM 的永久代中会发生垃圾回收么?

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收 (Full GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免 Full GC 是非常重要的原因。

(注:Java8 中已经移除了永久代,新加了一个叫做元数据区的 native 内存区) 

6、在 Java 中,对象什么时候可以被垃圾回收?

当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。

 7、Java 中的两种异常类型是什么?他们有什么区别?

Java 中有两种异常:受检查的 (checked) 异常和不受检查的 (unchecked) 异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用 throws 语句在方法或者是构造函数上声明。还有一些 Java 异常处理的小建议,我的专栏里都有提到。

8、JVM 垃圾回收算法

标记 - 清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当一块内存用完了,将还存另外一块上面,然后在把已使用过的内存空间一次清理掉。

标记 - 整理算法:标记过程与“标记 - 清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所一端移动,然后直接清理掉端边界以外的内存。

分代收集算法:一般是把 Java 堆分为新生代和老年代,根据各个年代的特点采用最适当的收集算法。新生代都发现有大批对象死去,选用复制算法。老年代中因为对象存活率高,必须使用“标记 - 清理”或“标记 - 整理”算法来进行回收。

 

 

这篇关于1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/993534

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2