博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一篇搞懂java、javac版本不匹配发生的原因
阅读量:2055 次
发布时间:2019-04-28

本文共 2894 字,大约阅读时间需要 9 分钟。

问题描述

当我们使用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)等。

 

图片来源(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能正常运行,并能快速进行版本切换。

转载地址:http://onnlf.baihongyu.com/

你可能感兴趣的文章
【F12】九个Console命令,让js调试更简单
查看>>
【数据库】left join(左关联)、right join(右关联)、inner join(自关联)的区别...
查看>>
【雅思】【写作】【大作文】Advantage VS. Disadvantage
查看>>
【雅思】金山词霸-单词学习(41-80)
查看>>
【雅思】【写作】【大作文】Report
查看>>
【雅思】【作文】顾家北100句翻译
查看>>
【雅思】【写作】【大作文】Discuss both views and give your own opinion
查看>>
【托业】【金山词霸】21-42
查看>>
【托业】【金山词霸】单词1-20
查看>>
【Python】脚本运行报错:IndentationError: unindent does not match any outer indentation level...
查看>>
【JMeter】前置处理器
查看>>
【Linux】top命令详解
查看>>
【黑盒测试】测试用例的常用方法
查看>>
【Linux】阿里云服务器部署--禅道
查看>>
【Loadrunner】Loadrunner 手动关联技术
查看>>
【性能测试】性能测试表
查看>>
【Mock】mock基础、简单的单元测试代码练习。
查看>>
【Loadrunner】Loadrnner 参数化策略
查看>>
【WebDriver】WebDriver 常用操作
查看>>
【Selenium】selenium中隐藏元素如何定位?
查看>>