java和jre【java深度历险笔记】

《java深度历险》中介绍javac.exe是个包装类,其实javac.exe也是用java语言来实现的,那么它的运行是需要jre的支持的,所以

在java安装目录下有个jre,如图中所示,是为了用来支持javac等执行的。
那么java.exe用的应该是哪一套jre呢?可以自己指定。书中说明了这样一套流程
在执行命令java.exe时,【首先该命令的运行目录应该添加至PATH中,或者给命令添加绝对路径】
如图中红线所示,如果在下载完JDK后,添加path后就会出现java选项。如果将以上两条删除【并且确认C:\Windows\system32中没有java.exe,此处关于C:\Windows\system32另插一个实验,在最后,修改系统变量后需要重启命令终端】。那么系统会提示
(图中红圈是我将java_path修改成“ ”后替换的内容,说明已经没法找到java.exe了,结果是无法识别‘java’命令)
接着我再加上 ‘ java安装目录\bin',此时应该能够找到java 命令,并且提示选项,如果输入-version会显示当前的jre version
现在就回到书上关于jre的解释。
书上说明,根据java.exe查找jre的路径是这样的
1.先查找java.exe同目录下是否有jre文件【文中说这样说并不准确,但是没有给出明确的解释】
2.查找java安装目录下是否有jre
3.查找注册表中的jre地址
Windows Registry(HKEY_LOCAL_MACHINE\Software\JavaSoft\Java

Runtime Environment\)
那现在我就先来一个一个进行测试

首先,先把JDK1.8中附带的jre加入jave.exe同目录,java -version出来的结果依然是
不管那么多,我也不懂。先暂且认为和书中1中说的一样,在同目录下的说法并不准确。
接着,实验第二条。我将JDK 7下的jre文件重命名为jre_1.7,并且将JDK1.8的jre拷贝进去
之后目录便成了这样
 
然后我们再进行测试 java -version
OK,现在已经成为了1.8了,结果如下
好的,说明书上说的很正确,就是这样。再接下来,我们再来看看注册表
用regedt32.exe打开注册表
注册表我也不懂是什么意思。但是为了测试注册表,那我让前面两个条件都失效。
哦先等等,我认为jre的查找可能也能通过系统变量中的path来,那么先把前面两个都失效,然后再加上jre的路径。
【在用户变量里面设置的变量,在系统变量中无法读取;反过来是能够读取的成立】
在红线目录中,有一个jre,是1.8版本的,现在我们再试试能不能成功

结果应该是不行的,那么也就说jre并不通过path中访问,是和java.exe所在目录有关的。
出现上述红线中的错误是因为我修改了注册表中的jre地址。既然出现了这个错误,说明这时它已经开始查找注册表了。
这个是1.7版本的注册表内同,jre7_1地址为错误的,也就是造成了上述could not open的错误的原因。
再解释一下,这个jre的版本地址并不是在JDK安装目录下,是在安装时另外选择的jre。
修改完成后,这结果说明确实是通过注册表来查找的。
最后书上有一个题目,是需要人为造出这种问题
很容易啊,修改注册表的currentVersion成为1.8就行了。
但是在此处,我不明白注册表的流程,书上解释说版本指向的是下面的相应配置【图中1.8对应只是为了方便,懒得修改】,应该是没有问题的,因为前面我们修改的错误的jre地址就是修改的1.7的地址。
但是这个问题让我觉得很奇怪,1.7required是从何而来,因为java.exe是1.7版本的JDK中来的吗?猜想一下,那么我把JDK1.8中的java.exe运行一下。
结果意料之中,那么现在把同目录下的jre改名字,迫使它进行读取注册表的操作。
注册表此时是1.8版本的
注册表出现错误,肯定的了,因为根本没有1.8版本的选项【为什么没有我不清楚,jdk换来换去我都忘了,至于能不能自己添加我也不明白,目前我没有必要;而且Windows注册表这个东西我也不怎么了解】
那么如果把currentVersion版本改成1.7呢
此时我们可以肯定了,就是根据java.exe的版本【书中解释过这个包装的原理,此处不解释】来决定的。
然后我们再把1.7版本的注册表,修改为下图,再来试试java -version。此时不多说,version必然是1.8版本的
结果没问题
以上的修改都是为了实验书中的介绍,至于如果使用1.7版本的java.exe,注册表或者同目录下的jre是1.8版本的会出现什么问题。我不清楚,目前也不是很想了解。希望之后在对java的机制有所研究后能够明白。
为什么不通过注册表的时候,直接修改JDK下面的jre文件不会存在这种情况呢,我也不清楚。
不管怎么样,以上都是实验,我们没有必要在进行实际开发中把jre版本换来换去,只要知道自己用的是哪个版本的jre,jdk,那样的话之后如果库之类,或者出现上述我实践的时候出现的问题不会一头雾水,至少有所明白。
 
附加
在之前我有听过关于system32中的作用,大概就是从这个文件加中寻找相应命令对应的可执行文件。在最开始的时候我的系统中system32是存在java.exe文件的。但我把它删除了。因此这次所有的试验都与它无关。我有些好奇在system32中的java.exe是如何找到jre的,初步猜测是注册表,于是我把JDK1.7中附带的java.exe复制了进去。把之前的java.exe的path删除得到的结果是
我一开始就想定论说,system32中的java.exe中查找是直接通过注册表进行。但后面突然想想,java.exe只是个包装类,真正指向的是Tools中的一个main函数。
然后我决定把JDK1.7中的jre还原。如果此时用的JDK1.7中的jre,那么应该是1.7版本的,但是结果显示依然为
看来的确是通过注册表来实现的,或者是说 这个java.exe的实现查找的方式依然是通过相对路径来查找的,没有查找到就去找注册表了。
写道这里发现javac.exe才是包装类,java.exe并未明确说明,因为javac.exe是指向tool中的一个main函数,可能是通过相对路径判断。如果将javac.exe拷贝一份至system32中会出现什么情况呢?
无法成功,但是提示丢失的文件为jli.dll。当我决定下结论"java.exe能够正常运作,说明java.exe应该不是包装类"。但是后面发现我将java安装目录加入了path,并且将javac.exe移出至其他地方运行结果为【报could not find main】。怀疑并不是javac.exe是包装类引起的。为了解决这个问题,我想要将javac.exe和jli.dll共同移进system32中看报错是否能够变成could not find main。【这时已经设置了javac环境变量】当我只将javac.exe移入system32中就已经报could not find main的错了,所以说jli.dll的寻找应该是通过path的方式,查找了一下,相应的JDK有两处有jli.dll。根据书上逻辑,javac.exe是通过jre解析,也就是安装目录下的jre,所以猜想会是jre下的jli.dll。先把jre下的dll改名,发现无影响;再把同目录下的dll改名出现找不到dll。并且将jre下的dll还原,也无法找到dll因此,此处用的dll为同目录下的dll。但是如果是根据同目录来判断不科学,因为当java.exe拷贝至system32时,执行的时候就无法通过同目录来得到dll。所以只可能是在path中所有路径查找,根据这个猜想,将path改成了jre的路径。安装目录\bin\jli.dll改名为\bin\jli_1.dll
但此时已经不出现找不到jli.dll了,只是找不到main。
结论
1. jli.dll查找方式为通过path目录中寻找。
2.将javac.exe移到system32中出现找不到main方法(需要库存在),但是java.exe不存在。说明java.exe并不是包装类,而javac.exe是包装类


posted @ 2015-04-16 23:48  keroro_exe  阅读(344)  评论(1编辑  收藏  举报