假设你在C:\workspace下写了个HelloWorld.java,并顺利使用编译程序javac将之编译为HelloWorld.class,在不 切换路径的情况下,可以直接执行java HelloWorld来加载HelloWorld.class并运行当中所定义的行为。
如果你切换到C:\底下或是其它路径底下,那么该如何加载HelloWorld.class并执行呢?以下并不是正解:
java C:\workspace\HelloWorld
首先你要知道java这个指令是作什么用的?执行java,其实就是启动JVM,之后接下类别名称,表示由JVM载入该类别的.class并执行。
在 PATH 是什么? 中提过,当你在实体操作系统下执行某个指令时,操作系统会依PATH中的路径信息,试图找到可执行的档案(例如对Windows来说,就是.exe、.bat,对Linux等就是有执行权限的档案)。
在 为什么需 要 JVM? 中则提过,JVM是Java程序唯一认得的操作系统,对JVM来说,可执行文件就是扩展名为.class的档案。当你要想在JVM中执行某个它的可执行文件(.class)时,则JVM会依CLASSPATH中的路径信息来寻找。
作个简单的比照,可以很清楚地对照PATH与CLASSPATH:
实体操作系统依PATH中的路径信息来寻找可执行指令(对Windows就是.exe、.bat等,对Linux等就是有执行权限的档案)。
JVM(虚拟操作系统)依CLASSPATH中的路径信息来寻找可执行指令(.class档案)。
如何在启动JVM时告知可执行文件(.class)的位置?可以使用-classpath自变量来指定:
java -classpath c:\workspace HelloWorld
指定可执行文件(.class)时,不用加上.class扩展名,这跟在Windows下执行javac时,不用特别再加上扩展名(javac.exe)是类似的。如果有多个路径信息,则可以用分别区隔。-classpath有个缩写形式-cp。例如:
java -cp c:\workspace;c:\classes HelloWorld
与PATH类似地,JVM会依路径的顺序,找寻是否有对应的类别档案,先找到先赢,先找到先载入。如果在JVM的CLASSPATH路径信息中都找不到指定的类别档案,则会出现java.lang.NoClassDefFoundError的信息。
如果使用Java开发了一些程序作为链接库,这些链接库中的类别档案,会封装为JAR(Java Archive)档案,也就是扩展名为.jar的档案。JAR档案实际上是使用ZIP格式作压缩,当中包含一堆.class档案,之后还会介绍如何制作 JAR档案。总之,现在如果你拿到一个JAR档案,如何在CLASSPATH中设定?
答案是将JAR档案当作一个特别的文件夹,例如,你拿到一个abc.jar与xyz.jar,放在C:\lib底下,则执行时如果使用到该JAR档案中的类别,则可以如下:
java -cp c:\workspace;c:\lib\abc.jar;c:\lib\xyz.jar SomeApp
在使用IDE的时候,会在IDE的项目中设定(或有时称汇入)所谓的「链接库」,其实就是在IDE项目环境下的CLASSPATH中设定JAR档案的位置与名称。
事实上,不只执行时可以设定CLASSPATH,编译时也会需要设定CLASSPATH,例如你开发了一个Message.java:
public class Message {
private String text;
public Message(String text) {
this.text = text;
}
public String getText() {
return text;
}
}
编译完的Message.class是放在c:\classes之下。现在你在c:\workspace下写了个HelloWorld.java:
public class HelloWorld {
public static void main(String[] args) {
Message message = new Message(“Hello!World!”);
System.out.println(message.getText());
}
}
如果你直接编译HelloWorld.java,则会出现以下的讯息:
表面字义看来,叫作不认得Message是什么符号,这其实是编译程序不知道你的Message定义档在哪?也就是编译程序找不到Message.class在哪!你在编译时,必须告知所使用到的类别档案是放在哪边,指定的方式也是靠CLASSPATH:
javac -cp c:\classes HelloWorld.java
编译程序如果看到原始码中有使用到Message这个名称,就会试着找看看在类别路径中,有无Message.class,如果有就读取刚中的信息,看看相关方法等定义是否正确,然后才进行编译。
那么要执行时,也是得指定CLASSPATH,不过以下指定却会发生问题:
原 因其实很简单,因为你指定的类别路径是c:\classes,所以JVM只在c:\classes下找相关的.class档案,而当中并没有 HelloWorld.class,因为HelloWorld.class是位于c:\workspace下。你要这样指定才正确:
java -cp c:\workspace;c:\classes HelloWorld
那为什么执行第一个HelloWorld时,不用特别指定CLASSPATH?默认的CLASSPATH就会读取当前目录下的.class,但是如果你自行指定了CLASSPATH,则以你指定的为主。
如果有些类别路径很常使用,则你也可以透过环境变量设定,例如:
SET CLASSPATH=C:\classes;c:\lib\abc.jar;c:\lib\xyz.jar
当 你启动JVM时,也就是执行java时,或者是编译时,也就是使用javac时,不指定CLASSPATH,则会读取环境变量信息中的CLASSPATH 变量设定。同样地,这个设定在关闭这个文本模式之后,就会失效,下次必须重新设定。如果你希望每次开启文本模式都可以套用某个CLASSPATH设定的 话,则可以设定在系统变量或用户变量中。如果你执行或编译时,使用了-cp或-classpath来指定类别的路径所在,则以-cp或-classpath设定的为主。
实际上,CLASSPATH的路径设定,是给应用程序类别加载器(AppClassLoader)使用的信息。想要了解类别加载的方式,则要了解类别加载器机制,这是进阶议题,要在较后面的文件中才会谈到。
在Java SE 6前,如果目录下有很多.jar档案,则要一个一个.jar档案分别指定,才可以正确的设定Classpath,例如您可能在执行程序时,如下指定Classpath:
java –cp .;c:\jars\a.jar;c:\jars\b.jar cc.openhome.JNotePad
在Java SE 6中,您可以使用’*’来指定某个目录下的所有.jar档案,例如上例在Java SE 6中,可以如下指定:
java –cp .;c:\jars\* cc.openhome.JNotePad
Java SE 6中Classpath新的指定方式,也适用在系统环境变量的设定上。
分类目录
- arch/management (17)
- computer (38)
- java/j2ee (305)
- lnmpa (237)
- mac/iphone/ipad/android (11)
- mysql/oracle/postgresql (126)
- os/software (74)
- other (518)
- python (6)
- redis/memcached/mongo (31)
- sitebuild (143)
随便看看
标签云
程序员 创业 人生箴言 eclipse 快捷键 术语 索引 unix命令 vim wordpress java学习笔记 环境变量 oracle内置函数 index 人生 数据类型 nohup tuxedo mysql学习笔记 MS-DOS命令 servlet spring 职场进阶 职业进阶 服务器选购 服务器选型 apache JPA MongoDB 注解 tomcat 子女教育 jquery maven JVM aix命令 网络营销 java异常 seo 人生规划 关键字 css 网络推广 struts 系统优化 成长 frame iframe bluehost jdbc select 我的信仰 oracle函数 cookie HashMap 站长工具 乱码 ArrayList secureCRT jsp session tail find halt 事务 oracle单记录函数 算法 URL window table javascript操作表单元素 String 字符串处理 健康 http 域名 情感 more google A记录 域名解析 netstat 弹出对话框 弹出窗口 框架集 框架 excel 字符串 javascript函数 showModalDialog nginx number 数组 sql frameset 开源程序 java数组 软件 oracle服务友情链接
收藏链接