从 Java 的平台无关性引入的一系列面试题

在 Java 面试中,有一条很常见的询问路线:从对 Java 的认识,到谈 Java 的平台无关性,到 Java 中的反射机制,再到类加载机制,继而深入到双亲委派机制等。本文将根据这条路线,给出一份可供参考的回答,如有错误万望指正。(推荐读者们在回答的时候结合自己的认识和项目经历作答)

1、谈谈 Java 的 Compile Once,Run Anywhere

1.1、一次编译到处运行是如何实现的?

Java 程序从编写到运行需要经历这么个过程:首先编写 Java 源代码,然后通过 Javac 编译器将 Java 源代码编译成 .class 字节码文件,然后把字节码文件交给虚拟机,虚拟机会在执行 Java 程序的时候把字节码转换为机器码执行。

字节码文件是平台无关性的重要一环。同一个 Java 程序能够在 Linux,Windows 等不同平台上运行,是因为不同平台上安装了不同的 Java 虚拟机,这些不同的虚拟机会根据同一份字节码文件,转换成各个平台对应的机器码,从而使 Java 程序在不同的平台上运行。

按照这个逻辑,只要是符合规范的字节码文件就能通过虚拟机在不同平台运行,我们完全可以使用另一种语言编写程序,编写完后把程序编译为字节码文件,然后通过虚拟机在不同的平台上运行。现实中也确实存在运行于 Java 虚拟机之上的其他语言程序。

1.2、为什么 JVM 不直接将源码解析成机器码执行?

不同的机器安装不同的虚拟机,JVM 直接解析 Java 源码不是也能做到一次编译到处运行吗?

  1. 这样每次执行之前就要进行各种检查(这是编译成字节码前的工作),降低了执行效率。
  2. 上面提到的兼容其他语言的功能将无法实现。

2、JVM 是如何加载 .class 文件的?

JVM 是通过 Class Loader 类加载器来加载字节码文件的,在介绍如何加载之前要先讲讲它加载的目的地,也就是 Java 虚拟机。

2.1、JVM 的结构:

Java 虚拟机是通过 c/c++ 编写的,可以看作是一个模拟真实计算机的程序,通俗来说说它是一个跑在内存中的机器,而后面我们谈到的 JVM 的内存结构就是存放在我们真实计算机的内存中的。(后面我会直接讲 JVM 的内存)

JVM 大致可以分为四个模块:

  1. 类加载器:用于把字节码文件加载进运行时数据区

  2. 运行时数据区:字节码文件的不同部分会被放入运行时数据区的不同地方

  3. 执行器:执行字节码中的程序

  4. 本地代码接口:调用宿主计算机的一些本地方法( c/c++ 或其他语言编写的接口)

其中运行时数据区是 Java 虚拟机的精华所在,它把字节码文件中的数据按一定的格式和数据结构组织存放好,方便了执行器调用。

2.2、JVM 是如何加载 .class 文件的

JVM 是通过类加载器加载 .class 字节码文件的,而 JVM 中的类加载器不只一个,它是按照父子关系进行划分的,至于为什么要这么划分,这会涉及到双亲委派机制,这个稍后便讲。具体的父子关系如下:

  1. BootStrapClassLoader:最顶层的类加载器,由 C++ 编写,用于加载 Java 的核心类库

  2. ExtClassLoader:Java 编写,用于加载 Java 的扩展库

  3. AppClassLoader:Java 编写,用于加载应用程序所在目录下的 class 文件

  4. 自定义 ClassLoader:Java 编写,用于定制化加载

由不同类加载器的作用可以知道,不同加载器加载的路径是不同的。但它们共同的任务都是把字节码文件加载到运行时数据区中(不同语言实现的类加载器具体加载部分的代码也会有所差别),更形象地说是把字节码文件中的二进制 01 数据加载到 JVM 中,并按照运行时数据区进行划分存放。

2.3、什么是双亲委派机制,为什么要制定双亲委派机制?

我们先从一个类的加载顺序开始讲起:

  1. 当需要加载一个类时,如果没有自定义类加载器,默认会使用 AppClassLoader 进行加载,

  2. AppClassLoader 先会查找一下该类是否已经被加载,若已经被加载则返回,若没有则调用它的父加载器 ExtClassLoader 进行加载,

  3. ExtClassLoader 也会查找一下该类是否已经被加载,若已经被加载则返回,若没有则向上调用它的父加载器 BootStrapClassLoader 进行加载,

  4. BootStrapClassLoader 会尝试加载该类,若加载不到则返回

  5. 接着 ExtClassLoader 也会尝试加载该类,若加载不到则返回

  6. 接着 AppClassLoader 也会尝试加载该类,假设该类被加载到(在项目目录下),则成功返回,否则抛出 ClassNotFoundException

当然以上过程也可以从自定义的类加载器开始,过程是一样的。这种先委派父加载器进行加载的机制就是双亲委派机制。

为什么不直接加载,而是往上委派双亲加载呢?

  1. 因为内存资源是宝贵的,如果一个类已经加载过一次了,也就没有必要再加载一份相同的拷贝在内存中了。为了保证一个类只被加载一次,加载类时就会从最顶层的父类加载器开始加载,只要加载过了,在后续需要用的时候就会返回已经加载过的 class 文件。

  2. 为了保证安全性和稳定性。Java 自身是有许多核心类的,这些类都通过顶层的父加载器进行加载,保证运行的时候用的是 Java 系统自己的类。如果没有双亲委派机制保证,用户自己也可以编写一些系统类并用自己编写的类加载器进行加载,那么就会导致Java 自身的系统类和用户编写的类混在一起,破坏了 Java 程序执行的安全性和稳定性。

2.4、额外谈谈 Java 中的反射机制

在问到类加载,JVM 等话题时难免会问到反射机制,这里补充一下:

反射是 Java 中一个很强大的机制,要说清楚反射还得结合上面说到的 JVM 结构去谈。

由于类加载器会把整个 .class 文件加载进运行时数据区,.class 文件中包含了一个类的字段,构造函数,以及各种方法,Java 允许我们在程序中通过反射的方式直接操作这些数据。

//比如我们可以根据类的限定类名获得一个类的实例对象
Class cc = Class.forName("xx.xx.Demo");
Demo demo = (Demo)cc.newIntance();

//获取并设置一个类的私有字段
Field name = cc.getDeclaredFied("name");
name.setAccessible(true);
name.set(demo, "Zhang san");

//或者调用一个类的方法(公有/私有)
Method sayHi = cc.getMethod("sayHi", String.class);
sayHi.invoke(demo, "Hello");

总结一句就是字节码中的类信息被加载进了运行时数据区,Java 允许我们在程序中直接操作这些类信息。

为什么说 Java 的反射机制强大呢?这里就要说到 Spring 框架了。不知道 Java 的反射强大,总该知道 Spring 框架的强大了吧,Spring 就是基于反射实现的。举个例子:Spring 中最核心的概念莫过于控制反转了,通俗的解释就是把对象的生命周期交给框架管理,而不是由程序员管理。既然是交给框架管理对象,那创建对象就不能通过 new 关键字实现了,而是由框架通过反射创建,同理对象中方法的调用也由框架通过反射进行调用。

End

如有收获,请帮忙转发,您的鼓励是作者最大的动力!

640?wx_fmt=png

640?wx_fmt=jpeg

我是本周的小编「子悠」,现在要隆重地告诉大家一个好消息,对于加入「Java极客技术」知识星球的同学提供基本的福利:

文章有疑问的地方可以提问,其他工作问题都可以提问出来,作者免费作答。

 https://t.zsxq.com/Y3fYny7

每周都有大牛分享一些面试题,和面试注意的知识点!

 https://t.zsxq.com/2bufE2v

每周由Java极客技术独家编制的设计模式与大家分享!

 https://t.zsxq.com/3bUNbEI

每两周还会分享一个话题,和大家一起成长!

 https://t.zsxq.com/BI6Unm2

还有Java极客技术团队亲自录制了一套 Spring Boot 视频,这套视频加密,加密后放到云盘上,下载链接加密之后,一机一码,每个星球的用户一个播放授权码。

 

我们做知识星球的目的和其他星主一样,就是为了帮助大家一起更好的成长,与高手拉近距离,减少差距,其实你也是高手!

640?wx_fmt=png
640?wx_fmt=jpeg
640?wx_fmt=jpeg
640?wx_fmt=jpeg
640?wx_fmt=jpeg

长按二维码

640?wx_fmt=jpeg

640?wx_fmt=png

Java 极客技术公众号,是由一群热爱 Java 开发的技术人组建成立,专注分享原创、高质量的 Java 文章。如果您觉得我们的文章还不错,请帮忙赞赏、在看、转发支持,鼓励我们分享出更好的文章。

640?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于YOLOv9实现工业布匹缺陷(破洞、污渍)检测系统python源码+详细运行教程+训练好的模型+评估 【使用教程】 一、环境配置 1、建议下载anaconda和pycharm 在anaconda中配置好环境,然后直接导入到pycharm中,在pycharm中运行项目 anaconda和pycharm安装及环境配置参考网上博客,有很多博主介绍 2、在anacodna中安装requirements.txt中的软件包 命令为:pip install -r requirements.txt 或者改成清华源后再执行以上命令,这样安装要快一些 软件包都安装成功后才算成功 3、安装好软件包后,把anaconda中对应的python导入到pycharm中即可(不难,参考网上博客) 二、环境配置好后,开始训练(也可以训练自己数据集) 1、数据集准备 需要准备yolo格式的目标检测数据集,如果不清楚yolo数据集格式,或者有其他数据训练需求,请看博主yolo格式各种数据集集合链接:https://blog.csdn.net/DeepLearning_/article/details/127276492 里面涵盖了上百种yolo数据集,且在不断更新,基本都是实际项目使用。来自于网上收集、实际场景采集制作等,自己使用labelimg标注工具标注的。数据集质量绝对有保证! 本项目所使用的数据集,见csdn该资源下载页面中的介绍栏,里面有对应的下载链接,下载后可直接使用。 2、数据准备好,开始修改配置文件 参考代码中data文件夹下的banana_ripe.yaml,可以自己新建一个不同名称的yaml文件 train:训练集的图片路径 val:验证集的图片路径 names: 0: very-ripe 类别1 1: immature 类别2 2: mid-ripe 类别3 格式按照banana_ripe.yaml照葫芦画瓢就行,不需要过多参考网上的 3、修改train_dual.py中的配置参数,开始训练模型 方式一: 修改点: a.--weights参数,填入'yolov9-s.pt',博主训练的是yolov9-s,根据自己需求可自定义 b.--cfg参数,填入 models/detect/yolov9-c.yaml c.--data参数,填入data/banana_ripe.yaml,可自定义自己的yaml路径 d.--hyp参数,填入hyp.scratch-high.yaml e.--epochs参数,填入100或者200都行,根据自己的数据集可改 f.--batch-size参数,根据自己的电脑能(显存大小)自定义修改 g.--device参数,一张显卡的话,就填0。没显卡,使用cpu训练,就填cpu h.--close-mosaic参数,填入15 以上修改好,直接pycharm中运行train_dual.py开始训练 方式二: 命令行方式,在pycharm中的终端窗口输入如下命令,可根据自己情况修改参数 官方示例:python train_dual.py --workers 8 --device 0 --batch 16 --data data/coco.yaml --img 640 --cfg models/detect/yolov9-c.yaml --weights '' --name yolov9-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15 训练完会在runs/train文件下生成对应的训练文件及模型,后续测试可以拿来用。 三、测试 1、训练完,测试 修改detect_dual.py中的参数 --weights,改成上面训练得到的best.pt对应的路径 --source,需要测试的数据图片存放的位置,代码中的test_imgs --conf-thres,置信度阈值,自定义修改 --iou-thres,iou阈值,自定义修改 其他默认即可 pycharm中运行detect_dual.py 在runs/detect文件夹下存放检测结果图片或者视频 【特别说明】 *项目内容完全原创,请勿对项目进行外传,或者进行违法等商业行为! 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值