JDK,JRE,class及jar的导入

来源:互联网 发布:跟章泽天是校友 知乎 编辑:程序博客网 时间:2024/06/04 19:44

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 等),而且他们都放置在<jdk 安装目录>\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.javajavac就是对上面命令的封装 所以tools.jar不用加到classpath里面K

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

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

0 0