前言:
由于这两个问题新手问得较多 且回答比较零散 很难统一整理 所
以就直接写了一篇 还请大家见谅
正文:
一 类路径 (class path)
当你满怀着希望安装好了 java 然后兴沖沖地写了个 hello world然后编译
运行 就等着那两个美好的单词出现在眼前 可是不幸的是 只看到了 Cant find
class HelloWorld 或者 Exception in thread main javalangNoSuchMethodError: maain
为什么呢? 编译好的 class 明明在呀
我们一起来看一看 java 程序的运行过程 我们已经知道 java 是通过 java
虚拟机来解释运行的 也就是通过 java 命令 javac 编译生成的 class
文件就是虚拟机要执行的代码 称之为字节码(bytecode) 虚拟机通过 classloader
来装载这些字节码 也就是通常意义上的类 这里就有一个问题 classloader 从
哪里知道 java 本身的类库及用户自己的类在什么地方呢? 或者有着缺省值(当前路径)
或者要有一个用户指定的变量来表明 这个变量就是类路径(classpath) 或者在运行
的时候传参数给虚拟机 这也就是指明 classpath 的三个方法 编译的过程和运行
的过程大同小异 只是一个是找出来编译 另一个是找出来装载
实际上 java 虚拟机是由 java luncher 初始化的 也就是 java (或 javaexe)
这个程序来做的 虚拟机按以下顺序搜索并装载所有需要的类:
引导类: 组成 java 平台的类 包含 rtjar 和 injar 中的类
扩展类: 使用 java 扩展机制的类 都是位于扩展目录($JAVA_HOME/jre/lib/ext)
中的 jar 档案包
用户类: 开发者定义的类或者没有使用 java 扩展机制的第三方产品 你必须在
命令行中使用 classpath 选项或者使用 CLASSPATH 环境变量来确定这些类的位置 我
们在上面所说的用户自己的类就是特指这些类
这样 一般来说 用户只需指定用户类的位置 引导类和扩展类是自动寻找的
那么到底该怎么做呢? 用户类路径就是一些包含类文件的目录 jar zip 文件的
列表 至于类具体怎么找 因为牵扯到 package 的问题 下面将会说到 暂时可认为
只要包含了这个类就算找到了这个类 根据平台的不同分隔符略有不同 类 unix 的系
统基本上都是 : windows 多是 ; 其可能的来源是:
* 即当前目录 这个是缺省值
* CLASSPATH 环境变量 一旦设置 将缺省值覆盖
* 命令行参数 cp 或者 classpath 一旦指定 将上两者覆盖
* 由 jar 参数指定的 jar 档案包 就把所有其他的值覆盖 所有的类都来自这个指 定的档案包中 由于生成可执行的 jar 文件 还需要其他一些知识 比如 package 还有 特定的配置文件 本文的最后会提到 可先看看 jdk 自带的一些例子我们举个 HelloWorld 的例子来说明 先做以下假设:
* 当前目录是 /HelloWorld (或 c:\HelloWorld 以后都使用前一个)
* jdk 版本为 (linux 下的)
* PATH 环境变量设置正确 (这样可以在任何目录下都可以使用工具)
* 文件是 HelloWorldjava 内容是:
public class HelloWorld
{
public static void main(String[] args)
{
Systemoutprintln(Hello World!\n);
Systemexit();
}
}
首先这个文件一定要写对 如果对 c 熟悉的话 很有可能写成这样:
public static void main(int argc String[] argv)
{
}
这样是不对的 不信可以试一试 由于手头没有 java 的规范 所以 作如下猜想: java 的 application 程序 必须以 public static void main(String[]) 开始 其他不一样的都不行
到现在为止 我们设置方面只设置了 PATH
当前路径就是指你的 class 文件在当前目录下
[HelloWorld]$ javac HelloWorldjava//这一步不会有多大问题
[HelloWorld]$ java HelloWorld// 这一步可能就会有问题
如果出了象开头那样的问题 首先确定不是由于敲错命令而出错 如果没有敲错命令
那么接着做:
[HelloWorld]$ echo $CLASSPATH
或者
c:\HelloWorld>echo %CLASSPATH%
看看 CLASSPATH 环境变量是否设置了 如果设置了 那么用以下命令:
[HelloWorld]$ CLASSPATH=
或者
c:\HelloWorld> set CLASSPATH=
来使它为空 然后重新运行 这次用户类路径缺省的是 所以应该不会有相
同的问题了 还有一个方法就是把 加入到 CLASSPATH 中
[/]$ CLASSPATH=$CLASSPATH:
或者
c:\HelloWorld> set CLASSPATH=%CLASSPATH%;
同样也可以成功 Good Luck
当你的程序需要第三方的类库支持 而且比较常用 就可以采用此种方法比如常
用的数据库驱动程序 写 servlet 需要的 servlet 包等等 设置方法就是在环境变量中
加入 CLASSPATH 然后就可以直接编译运行了 还是以 HelloWorld 为例 比如你想在根
目录中运行它 那么你直接在根目录下执行
$ java HelloWorld
或者
c:\>java HelloWorld
这样肯定会出错 如果你的 CLASSPATH 没有改动的话 我想大家应该知道为什么错了吧 那么怎么改呢? 前面说过 用户类路径就是一些包含你所需要的类的目录 jar 档案 包 zip 包 现在没有生成包 所以只好把 HelloWorldclass 所在的目录加到 CLASSPAT 了 根据前面的做法 再运行一次 看看 呵呵 成功了 换个路径 又成功了!! 不仅仅? 以直接运行其中的类 当你要 import 其中的某些类时 同样处理
不知道你想到没有 随着你的系统的不断的扩充 (当然了 都是一些需要 java 的东挝? 如果都加到这个环境变量里 那这个变量会越来越臃肿 虽然环境变量空间可以开很大 总 觉得有些不舒服 看看下面一个方法
在命令行参数中指明 classpath
还是和上面相同的目标 在任何目录下执行 HelloWorld 用这个方法怎么实现呢?
[/]$ java cp /HelloWorld HelloWorld
或者
c:\>java cp c:\HelloWorld HelloWorld
就可以了 这是这种方法的最简单的应用了 当你使用了另外的包的时候 还可以采用另一种方法 例如:
$ javac classpath aPath/aPackagejar: myJavajava
$ javacp aPath/aPackagejar: myJava
或者
c:\> javac classpath aPath\aPackagejar; myJavajava
c:\> javacp aPath\aPackagejar; myJava
这种方法也有一个不方便的的地方就是当第三方包所在的路径较长或者需要两个以上包包?
时候 每次编译运行都要写很长 非常不方便 这时候可以写脚本来解决 比如一个例子:
compile (文件 权限改为可执行 当前目录)
$ cat compile
#!/bin/bash
javac classpath aPath\aPackagejar:anotherPath\anotherPackagejar: myJavvajava
run (文件 权限改为可执行 当前目录)
$cat run
#!/bin/bash
java cp aPath\aPackagejar:anotherPath\anotherPackagejar: myJava
或者:
compilebat
c:\HelloWorld> type compilebat
javac classpath aPath\aPackagejar:anotherPath\anotherPackagejar: myJavvajava
runbat
c:\HelloWorld> type runbat
java cp aPath\aPackagejar:anotherPath\anotherPackagejar: myJava
就可以了 试试看
前面提到了扩展类 扩展类是什么呢? java 的扩展类就是应用程序开发者用来
扩展核心平台功能的 java 类的包(或者是 native code) 虚拟机能