一篇搞懂java、javac版本不匹配发生的原因

2023-11-08

问题描述

当我们使用IDE或cmd进行java编译时,有时会发生这样的错误:

Error:A JNI error has occurred,please check your installation and try again. 

异常部分描述为:

Exception in thread "main" java.lang.UnsupportedClassVersionError: has been compiled by a more recent version of the Java Runtime.

从异常描述我们可以猜到在我们的计算机内存在多个版本的jre,而多个java版本可能不兼容。

于是我们在cmd内分别输入

java -version

javac -version

查看二者显示的java版本,会发现他们的版本的确不一致。而这种情况大多数发生在我们安装新版本的Java后。

java -version和javac -version返回的究竟分别是什么?

java -version会返回系统最新安装的jdk版本,即本文最后一部分说的系统变量Path中的“Program Files(X86)\Oracle\java\javapath”路径下的java.exe版本;

而javac -version会返回环境变量中jdk目录下的某一版本,即系统在所配置的用户变量中%JAVA_HOME%\bin找到的java.exe所在的jdk版本。

为什么java version与javac version显示jdk版本会不一致,他们二者有什么关系?为什么他们不同会导致异常?若计算机内存在多个版本的jdk系统按照什么顺序寻找版本匹配的java?


JRE和JDK的基本关系

JRE(Java Runtime Environment)即Java运行环境,顾名思义,Java程序运行所必要的东西。JRE面向使用者而不是开发者,只能运行Java程序,而不能进行开发。常由Java虚拟机、面向使用者的工具元件、各种Java类库组成。(即上面异常中的Java Runtime ......)

JDK(Java Development Kit)即Java开发配套元件,为Java开发人员提供所需要的Java开发环境和运行环境,故JDK经常包含JRE。除JRE外,JDK还包含开发工具(bin中的javac等以及lib中额外的类库)及各种应用程序接口(API)等。

 

图片来源https://docs.oracle.com/javase/8/docs/(jdk8)

java.exe和javac.exe的关系

JDK安装完成后,在安装目录下能看到有两个目录分别为jdk与jre(以我安装的1.8为例)。

我们打开二者目录

 

jre目录下文件

 

jdk目录下文件

 

其中

bin:存放了各种可执行文件,比如:java.exe,javac.exe
include:存放与JVM交互所用头文件
legal:存放JDK各模块授权文档
lib:jre目录中中存放jar包,jdk目录中存放除了其目录下jre中lib存放的jar包扩充的jar包

我们发现二者几乎相同,但jdk比jre多了include和jre目录(这验证了我们jdk包含jre的说法)。然后我们打开jdk下的jre目录,经过与jre目录进行对比可以发现二者完全相同。

而jdk与jre使用bin内的javac.exe文件和java.exe进行编译运行,其中jdk使用javac.exe将.java文件编译为.class文件,jdk与jre使用java.exe运行编译好的.class文件。故jdk有java.exe和javac.exe,而jre只有java.exe。分别打开二者可以验证这一点。

但是当我们进行运行时,使用的是jdk中的jre的java.exe还是jre中的java.exe呢?

这个问题需要java.exe来解答:


java.exe按照顺序寻找合适的jre

当我们进行运行java程序时,会运行java.exe(需要根据环境变量寻找,发生异常原因,在下面的根本原因中会讲),他需要把.class文件放在JVM上运行,而JVM是jre的一部分,java.exe会按顺序寻找合适的jre运行java程序:

1.当前目录下的jre,即当前运行java.exe所在位置为jre\bin中

2.父目录下的jre,即当前运行java.exe所在位置为jdk\bin中

3.查询注册表[Java Runtime Environment]信息(及系统变量C:\Program Files (x86)\Common Files\Oracle\Java\javapath)

也就是说不管系统使用哪个java.exe,他需要按照当前路径找到版本对应的jre,当按顺序寻找完毕但未找到合适jre时,会进行报错。

此时即安装JDK常出现的问题,当我们进入cmd输入java -version和javac -version返回的版本号不一致。

我们知道正常情况下在jre或jdk的bin文件夹中运行java.exe不会出错(若非人为更改相应bin下java.exe的版本,则系统必在步骤1或2找到相应jre),那么什么情况下会导致我们错误地使用其他的java.exe呢?


安装新的jdk时Java自动配置原版本环境变量

当我们使用java.exe时,系统根据环境变量寻找java.exe,由于环境变量有先后顺序,于是我们可能找到不想找到的版本的java.exe。

在cmd中输入where java,可以看到系统找到java.exe的路径(可能不止一个)。

我们发现可能存在一个我们没有配置过的路径javapath,我们进入该路径查看,发现改目录下存放着java.exe,javaw.exe和javaws.exe。

当我们在计算机内安装新的jdk时,由于jdk版本改变,Java会自动配置环境变量指向原来版本的java.exe,javaw.exe和javaws.exe,将其命名为环境变量path,配置在系统变量中。

于是若由于某种原因我们配置的新jdk的环境变量在path的后面,则系统会先找到javapath下的java.exe,而该目录下的java.exe在寻找jre的步骤1、2中都不会找到相关jre,于是他在步骤3中寻找到的jre自然与javapath下源jdk的java.exe版本不符。

而剩下一种情况为人为因素导致的版本错误:

另一种情况是当我们把java.exe放在不同版本的jdk或jre的bin文件夹中:虽然一般在bin文件夹中由于bin必为当前版本jdk/jre的bin文件很难找不到合适的jre,若我们强行更换java.exe则会导致我们会在顺序1,2中找不到合适的jre,虽然这种情况一般不会发生。


总结

了解了系统运行java程序寻找java.exe的途径以及java.exe寻找合适jre的步骤,我们能避开可能发生的异常,使我们的计算机内即使存在多个版本的jdk能正常运行,并能快速进行版本切换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一篇搞懂java、javac版本不匹配发生的原因 的相关文章

随机推荐

  • 软件测试大作业 题目 网站测试,[软件分析与测试大作业] 测试性分析软件

    软件分析与测试 考试大作业 1 假设某单位内部电话号码由三部分组成 分别是 分机号 前缀 后缀 其中 分机号为空白或一位数字 前缀为非 0 开头的二位数字 后缀为非全0的3位数字 假定被测程序能接受一切符合上述规定的电话号码 拒绝所有不符合
  • 2023牛客暑期多校训练营7 I-We Love Strings (分块)

    文章目录 题目大意 题解 参考代码 题目大意 题解 这题给定的 n n n 大小和 s i s i si 的总长度有玄机
  • transformers学习笔记3

    创建model的方法 automodel创建预训练模型 使用automodel直接创建 使用的是hug face官网上的预训练好的模型参数 完成创建后再使用自己本地的数据集进行迁移训练 automodel api 去官网上下载用户指定类型模
  • com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

    com mysql cj jdbc exceptions CommunicationsException Communications link failure 这个问题就是本地sql没有开始 详情请看点击此处
  • 华为机试-称砝码

    文章目录 描述 输入描述 输出描述 代码解析 描述 现有n种砝码 重量互不相等 分别为 m1 m2 m3 mn 每种砝码对应的数量为 x1 x2 x3 xn 现在要用这些砝码去称物体的重量 放在同一侧 问能称出多少种不同的重量 注 称重重量
  • 地平线 AI 芯片工具链 - 03 自定义模型转换

    地平线 AI 芯片工具链 03 自定义模型转换 1 前提条件 2 文件目录 3 模型可视化 4 模型校验 5 模型编译 1 前提条件 地平线 AI 芯片工具链 01 配置安装 待转换模型 onnx 模型 其他类型可转为 onnx 模型 2
  • springboot项目如何开启热部署

    1 添加依赖
  • bert简单介绍和实践

    bert模型是Google在2018年10月发布的语言表示模型 在NLP领域横扫了11项任务的最优结果 可以说是现今最近NLP中最重要的突破 Bert模型的全称是Bidirectional Encoder Representations f
  • Scala下载及IDEA安装Scala插件(保姆级教程超详细)

    一 Scala的下载与安装 Scala语言可以在Windows Linux Mac OS等系统上编译运行 由于Scala是运行在JVM平台上的 所以安装Scala之前必须配置好JDK环境 JDK版本要求不低于1 5 本博客为基于Window
  • 使用Python批量修改文件名

    使用os rename fold newfilename 对文件重命名 coding utf 8 import os filename list os listdir for filename in filename list str re
  • 防火墙简介

    1 什么是防火墙 防火墙也被称为防护墙 它是一种位于内部网络与外部网络之间的网络安全系统 通常 防火墙可以保护内部 私有局域网免受外部攻击 并防止重要数据泄露 它实际上是一种隔离技术 在没有防火墙的情况下 路由器会在内部网络和外部网络之间盲
  • Free MyBatis plugin插件搜不到

    Free MyBatis plugin IntelliJ IDEs Plugin Marketplacehttps plugins jetbrains com plugin 8321 free mybatis plugin versions
  • AXIS2+Myeclipse 开发 Webservices

    一 准备工作 1 安装JDK 我使用的是版本是JDK1 6 下载地址 http java sun com javase downloads index jsp 下载那个rpm的bin包 即jdk 6u1 linux i586 rpm bin
  • 域名与服务器如何绑定?

    新手如何快速搭建自己的云服务器 来源 https www cnblogs com yspace p 10050452 html 相信很多小白对于服务器这个概念可能理解得很模糊 其实服务器说白了就是一台供你远端使用且可以一直开机的电脑而已 说
  • es设置数据备份--新建仓库

    前言 设置es备份首先要新建仓库 然后在kibana中配置 备份策略 多长时间备份一次等 存储库的安装 创建存储库 必须先注册快照存储库 才能执行快照和还原的操作 如果多个集群同时注册同一个快照存储库 只有一个可以有写权限 其余集群设置为r
  • centos6.5 MySQL安全模式修改Root 密码

    错误情况描述 mysql u root p ERROR 1045 28000 Access denied for user root localhost using password YES 解决办法 第一步 关闭MySQL服务 servi
  • 使用Python对Excel文件进行处理的小技巧

    Excel文件是一个常用的电子表格文件格式 它可以包含大量的数据和公式 Python有很多库可以用来处理Excel文件 下面介绍其中一些常用的库和技巧 目录 1 使用pandas库读取Excel文件 2 使用openpyxl库进行Excel
  • 内存管理分配,连续分配、分页存储、分段存储、段页式

    目录 1 连续分配管理 1 1 固定分区分配 1 2 动态分区分配 2 非连续分配方式 2 1 基本分页式内存分配管理 2 1 1 基本分页式内存思想与方法 2 1 2 进程逻辑地址与内存物理地址如何转换 2 1 3 页面在内存中的起始地址
  • typescript对与axios的封装

    import Modal message from antd import axios AxiosError AxiosRequestConfig AxiosResponse from axios import AdminConfig fr
  • 一篇搞懂java、javac版本不匹配发生的原因

    问题描述 当我们使用IDE或cmd进行java编译时 有时会发生这样的错误 Error A JNI error has occurred please check your installation and try again 异常部分描述