JDK,JRE,class及jar的导入

Java中的jdk,jre,以及jar的导入

基本概念

JDK : Java Development Kit —— java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。

SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。

JRE : Java Runtime Enviroment —— java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。

JVM : Java Virtual Mechinal —— JAVA虚拟机。JVM是JRE的一部分,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 的主要工作是解释自己的指令集(即字节码)并映射到本地的 CPU 的指令集或 OS 的系统调用。Java语言是跨平台运行的,其实就是不同的操作系统,使用不同的JVM映射规则,让其与操作系统无关,完成了跨平台性。JVM 对上层的 Java 源文件是不关心的,它关注的只是由源文件生成的类文件( class file)。类文件的组成包括 JVM 指令集,符号表以及一些补助信息。

区别

JRE主要包含:java类库的class文件(都在lib目录下打包成了jar)和虚拟机(jvm.dll);JDK主要包含:java类库的 class文件(都在lib目录下打包成了jar)并自带一个JRE。那么为什么JDK要自带一个JRE呢?而且jdk/jre/bin下的client 和server两个文件夹下都包含jvm.dll(说明JDK自带的JRE有两个虚拟机)。

安装单一版本的jdk时,可能会多个java.exe(搜一下)和两个JRE环境,

  1. Public JRE (指[JRE_lcation])
  2. Private JRE (指[JDK_location]\jre)

JRE的地位就象一台PC机一样,我们写好的Win32应用程序需要操作系统帮我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。所以当你装完JDK后,如果分别在硬盘上的两个不同地方安装了两套JRE,那么你可以想象你的电脑有两台虚拟的Java PC机,都具有运行Java程序的功能。所以我们可以说,只要你的电脑安装了JRE,就可以正确运行Java应用程序。

1、为什么Sun要让JDK安装两套相同的JRE?

JDK里面也附上了很多用 Java 所撰写开发工具(例如 javac.exe、jar.exe 等),而且他们都放置在 \lib\tools.jar 这个档案之中。

Java 的编译器 javac.exe 也是用 Java 撰写的? 

javac.exe明明就是一个执行档,用 Java 撰写的程式应该是.class 档才对。

为了证明这件事情,底下我们做个小实验,证明我所言不假:

先将tools.jar改名为tools1.jar,然后运行javac.exe,显示如下结果: Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main 这个意思是说,你输入javac.exe与输入 java -cp c:\jdk\lib\tools.jar com.sun.tools.javac.Main 是一样的,会得到相同的结果。
从这里我们可以证明javac.exe只是一个包装器(Wrapper),而制作的目的是为了让开发者免于输入太长的指命。实际上

tools.jar 是系统用来编译一个类的时候用到的,即执行javac的时候用到  
javac XXX.java 实际上就是运行
java -Calsspath=%JAVA_HOME%\lib\tools.jar xx.xxx.Main XXX.java
javac就是对上面命令的封装 所以tools.jar不用加到classpath里面K

从这里我们可以得出一个结论:

JDK 里面的工具几乎是用 Java 所撰写的,所以 JDK 本身就是 Java 应用程式,因此要使用 JDK 附的工具来开发 Java 程式,也必须要自行附一套 JRE 才行,这就是 \jre 底下需要一套JRE 的原因。而 Public JRE 就是拿来执行我们自己所撰写的 Java 应用程式。不过,两套中任何一套 JRE 都可以拿来执行我们所撰写的Java 应用程式,可是 JDK 内附的开发工具在预设使用包装器(.exe)来启动的情形下,都会自己去选用 \jre 底下那套 JRE。

2、如果一台电脑安装两套以上的JRE,谁来决定呢?

这个重大任务就落在java.exe身上。Java.exe的工作就是找到合适的JRE来运行Java程序。
Java.exe依照底下的顺序来查找JRE:

  1. 自己的目录下有没有 JRE 目录。 (这个部分这样说并不是非常精确,原因请详见JDK原始码,这此不特别说明)
  2. 父目录底下JRE子目录。
  3. 查 询 Windows Registry(HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment)。

当您在开发 Java 程式或是执行Java程式的时候,一定要记得两件事:

  1. 哪一个java.exe 被执行。
  2. java.exe 找到哪一套 JRE。

情况

  • case 1: 若path的顺序是\WINDOWS\system32 在 [JDK location]\bin 之前。
    java指令便是执行\WINDOWS\system32\java.exe。
    由于windows下无jre目录,所以会参考Window Registry下的jre。(即前述的Public JRE)
  • case2:
    若path 的顺序是[JDK_location]\bin 在\windows\system32 之前。
    那么java指令便是执行C:[JDK_location]\bin\java.exe。
    由于jdk下有一个jre目录,所以java会参考jdk\jre。(即前述的Private JRE)

最常发生的问题是当path的顺序如case1,java指令找到的jre与javac找到的jre是不同的,这可能就会出现问题
在jar中会有阐述

JAR,Class

JAR : Java Archive —— Java归档文件

Java找寻class的顺序

根据JDK文件说明,java 3种类加载器

  1. Bootstrap classes
  2. Extension classes
  3. Users classes

父类加载器加载的类是看不见子类加载器加载的类的,反过来,子类加载器加载的类也不能访问父类加载器加载的类的“友好”成员,尽管可能它们可能具有相同的包名。

这样的设计能够避免不信任的应用类破坏和干扰可信任的系统类,从而保证 Java 系统的安全。

另外,默认情况下,放在 lib/ext 中的类拥有所有的权限。参考 $JAVA_HOME/jre/lib/security/java.policy 文件。

所以,如果是可信任类,最好放在 ext 目录下,以受到保护。

当然这里说得太简单,有兴趣可以研究一下 Java 虚拟机原理和 Java 安全。

Bootstrap classes

指的是java在启动时加载的class,这些class主要是rt.jar和jre/lib目录下的一些class。
(所以rt.jar可以不须加入classpath)

Extension classes

指的是jre/lib/ext目录下的jar或zip档。

third-party的library通常会放在这目录下,如java3d,jogl..等。当classloader需要resolve class时,jre会自动来此目录下找。如果不同名字的jar,却包含了相同的class,那么哪一个class被加载是不一定的。

当我们使用third-party的library时,如果只将jar档放在Private JRE/lib/ext中,javac指令因为使用Private JRE,所以能够找到third-party library,得以顺利compile。但java指令使用的是Public JRE,Public JRE找不到third-party library,以致无法顺利执行,原因是无法import package。

解决的方法有:

  1. 将third-party library jar档在private JRE/public JRE各放一份。
  2. 设定path时,使java及javac指都优先使用Private JRE。
  3. IDE导入

另一种方法能让Java运行环境查找和装载这些extension classes,称为The Extension Mechanism 扩展机制,在此就不详述了。

user classes

User classes便是指我们在classpath设定路径下的class。

如:若总是使用c:\java\的class,或是需要使用c:\lib\test.jar里的library,
便可以set classpath =.;c:\java\;c:\lib\test.jar

问题:为什么要单独写jar呢,而不写目录呢?
答 : 写目录的话表示目录下的所有class文件,不包含jar;如果要包含jar文件,可使用通配符'*'

  1. 若无设定classpath,jre预设找(.)目前目录是否存在target class.
  2. 若有设定classpath,jre只找classpath设定的路径是否存在target class.
  3. 在console mode下使用-cp或-classpath,则jre只找参数后的路径是否存在target class.
  4. 在console mode使用-jar来指定jar档时,jre只找寻jar中是否存在target class.

详细可参考Setting the class path

eclipse中几种加入jar包方式的区别

jar导入到我们的web项目中的classpath下

  1. 直接用MyEclipse里自带的相关的项目jar包,右击项目“MyEclipse”菜单,选择对应的jar包就OK了,例 “Add Spring Capabilities”,并且可以设置Spring的一些配置信息,不错的可视化操作;

  2. 添加外部的jar包到web项目的lib包下,右击项目“Properties”-->“Java Build Path”-->“Libraries”选项卡(当然了,此操作下,不仅仅这一种添加jar包的方式);

  3. 自己手动拷贝jar文件到项目的lib包下,具体操作只要把要添加的jar文件拷贝到MyEclipse中的workspace下的lib包里就好了;

三种jar包添加方式的选择

  1. 这种方式,jar文件直接链接到MyEclipse的文件下,并没有拷贝到WEB-INF/lib目录下,不得用项目的发布、移植,可能会出现jar找不到的情形;

  2. 选择性比较的强,可以随意的加jar包,只要在你本机存在就可以了,链接的也是jar文件的绝对路径,缺点同1;

  3. 直接添加到WEB-INF/lib目录下,移植性强,可操作性也强。

Eclipse Java Build Path设置中

  • add jar是表示从你的工程里添加JAR,前提是你把jar已经放到自己的工程目录里。
  • add external jar表示这个jar的位置需要URI来定位,需要给出全路径。
  • add library 是一些已经定义好的jar的集合,因为它们经常是一起用,所以简化了些操作,比如你做RCP开发的时候就会有个plugin library包含了运行工程所需要的基本插件。
  • add variable 类似于JAVA_HOME的配置
  • Add (external) class Loader 类似jar

其他

当出现java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener类似这种找不到Listener的异常时,要切记spring的jar包一定要放在工程的lib下这样才能避免这个错误的发生。

补充:虽说无论用什么方式导入包在本地运行都是一样的,但实事上我运行时,有的只有Java Build Path才起作用,有的只有导入到lib下才行。用Java Build Path导入包和把包复制到lib下是有区别的,它俩其实不会冲突,也没有什么关系的,Java Build Path是我们编译需要的包,在比如在import ..***时如果没用Java Build Path导入包的话类里面就有红叉,说不识别这个类;导入到lib下是程序运行时需要的包,即便用Java Build Path导入过的包,没放到lib下,运行项目时会出现ClassNotFoundException的异常。

你可能感兴趣的:(JDK,JRE,class及jar的导入)