CLASSPATH和PATH

      J2SDK(Software Development Kit for Java 2) ,简称JDK.它包括了JDK(Java Development Kit),JRE(Java Runtime Enviroment),Java Plug-in.
      JDK (Java Development Kit), Java开发工具包(C:\Java\jdk1.6.0_18\).JDK是一组API,也可以说是一些java Class。JDK是一切java应用程序的基础,所有的java应用程序是构建在这个之上的。
      JRE (Java Runtime Environment),Java运行环境.   说明:当安装过JDK之后会在c:\windows\system32下有一个java.exe,而系统的环境变量中%SystemRoot%\system32;是默认添加上的,而%SystemRoot%实际上就是C:\WINDOWS。 


      电脑有两套JRE,一套位于%JAVA_HOME%\jre另外一套位于C:\Java\jre6目录下。我们编写的Java程序要JRE才能运行,当你装完JDK后硬盘上的两套JRE都具有运行Java程序的功能,只是后者比前面那套少了Server端的VM,但是JDK里面的工具只能由"<JDK安装目录>\jdk1.6.0_18\"目录下的JRE来执行。server与client选项的差别在于所使用的VM不同,执行Java程序时默认会使用client VM。若使用server VM,会花费较长的启动时间及消耗较多的内存,为的是启动Java程序后可以获得较好的执行效能。  
      为什么会有两套JRE呢? 因为JDK里面有很多用Java所编写的开发工具(如javac.exe、jar.exe等),而且都放置在 <JDK安装目录>\lib\tools.jar里,它们本身运行的时候也需要一套 JRE,也就是前者(%JAVA_HOME%\jre);而后者(C:\Java\jre6)的JRE是用来执行我们自己编写的JAVA程序。
      设置JAVA_HOME,CLASSPATH,PATH的目的:
            1.设置JAVA_HOME(C:\Java\jdk1.6.0_18): 
                      一、方便引用,要使用这个路径的时候, 只需输入%JAVA_HOME%即可;
                      二、修改简单, 当JDK路径改变的时候, 仅需更改JAVA_HOME的即可;
                      三、第三方软件会引用约定好的JAVA_HOME变量
            2.设置PATH(%JAVA_HOME%\bin): 

                      让Java执行环境找到指定的工具程序如Java、javac,系统会在当前目录下查找,若没有找到会到系统PATH中查找。
            3.设置CLASSPATH:   

                      让Java执行环境找到指定的Java程序(也就是.class文件)。

Java运行时环境(JRE)查找启动类,并加载其他使用到的类(即当加载A时,发现A应用了B则再去加载B),从三个地方加载需要的类:bootstrap class path, the installed extensions, and the user class path。

                    JDK5.0默认会在当前工作目录以及JDK安装目录/lib中寻找Java程序,若Java程序在这两个目录中则不用设置classpath。classpath在编译和运行时都要用到的参数。当没有这个参数时,java 和 javac 命令会取环境变量 CLASSPATH 来代替。

package com.tools.lcr;
public class AppLauncher {
	public static void main(String [] args) {
		System.out.println("Hello World " + args[0]);
	}
}	

 

javac -classpath . AppLauncher.java  

        那么 javac 便会以当前目录(.)作为 classpath。你也可以先将环境变量 CLASSPATH 的值增加当前目录“.”,然后执行效果是一样的。

set CLASSPATH=.;%CLASSPATH%
javac AppLauncher.java      

      当 classpath 很长的时候,为了运行方便(package com.tools.lcr.AppLauncher),java 程序通常都会提供一个批处理文件(如 run.bat)。

rem 环境变量中已设置了JAVA_HOME
set JAVA=%JAVA_HOME%\bin\
set LIB=lib/json.jar;lib/saaj.jar;lib/log4j.jar;lib/jaxrpc.jar;lib/dom4j.jar 
set name=luchunli
%JAVA%\javac -d . AppLauncher
%JAVA%\java -Xms64m -Xmx256m -Duser.locale=zh_CN -classpath %LIB% com.tools.lcr.AppLauncher %name%

      那么就算 classpath 再长,也可以化整为零,比用环境变量方便的多,建议不要依赖于 CLASSPATH 环境变量。编译或运行时将这个变量赋给 classpath 参数即可。        

 

        rt.jar是JAVA基础类库,默认就在根classloader的加载路径里面(%JAVA_HOME%\jre\lib和C:\Java\jre6\lib)
       tools.jar JDK类库中提供的一些工具类集合的jar文件,是一个工具包(javac等工具)

 javac XXX.java
 实际上就是运行
 java -Calsspath=%JAVA_HOME%\lib\tools.jar  xx.xxx.Main  XXX.java
 javac就是对上面命令的包装器(wrapper),其目的是避免开发者输入过长的指令。

       dt.jar是关于运行环境的类库,主要是swing的包(%JAVA_HOME%\lib)  

将tools.jar改成tools_bak.jar
C:\src>javac AppLauncher.java
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/Main
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.Main
		at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
		at java.security.AccessController.doPrivileged(Native Method)
		at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
		at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
		at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
		at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: com.sun.tools.javac.Main.  Program will exit.

将tools.jar改回,将rt.jar改名为rt_bak.jar
C:\src>javac AppLauncher.java
           Error occurred during initialization of VM
           java/lang/NoClassDefFoundError: java/lang/Object

将rt.jar改名为rt_bak.jar
C:\src>java AppLauncher
           Error occurred during initialization of VM
           java/lang/NoClassDefFoundError: java/lang/Object

改变tools.jar对java执行没有影响
C:\src>java AppLauncher luchunli
           Hello World luchunli

      既然电脑上有两套JRE,那么由谁来决定用那一套JRE呢?java.exe的工作就是找到合适的JRE来运行Java程序。   
           java.exe依照底下的顺序来查找JRE:
                 自己的目录下有没有JRE;
                 父目录有没有JRE
                 查询注册表: [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 

      所以java.exe的运行结果与你的电脑里面哪个JRE被执行有很大的关系。

      环境变量PATH此时为%SystemRoot%\system32

C:\Documents and Settings\Administrator>java -verbose
	[Opened C:\Java\jre6\lib\rt.jar]
	[Loaded java.nio.charset.Charset$3 from C:\Java\jre6\lib\rt.jar]
	[Opened C:\Java\jre6\lib\charsets.jar]
	[Loaded sun.nio.cs.AbstractCharsetProvider from C:\Java\jre6\lib\rt.jar]
	[Loaded sun.nio.cs.ext.ExtendedCharsets from C:\Java\jre6\lib\charsets.jar]

     将system32下的java.exe修改成java_lcr.exe,添加环境变量%JAVA_HOME%\bin,环境变量此时为%SystemRoot%\system32;%JAVA_HOME%\bin;

C:\Documents and Settings\Administrator>java -verbose
	[Opened C:\Java\jdk1.6.0_18\jre\lib\rt.jar]
	[Loaded java.nio.charset.Charset$3 from C:\Java\jdk1.6.0_18\jre\lib\rt.jar]
	[Opened C:\Java\jdk1.6.0_18\jre\lib\charsets.jar]
	[Loaded sun.nio.cs.AbstractCharsetProvider from C:\Java\jdk1.6.0_18\jre\lib\rt.jar]
	[Loaded sun.nio.cs.ext.ExtendedCharsets from C:\Java\jdk1.6.0_18\jre\lib\charsets.jar]
	//......

     实际上此时我们查询注册表可以看到RunTimeLib指示的路径为:C:\java\jre6\bin\client\jvm.dll 


      java.exe程序只是一个执行的外壳,它会:
           1.创建JVM装载环境和配置
           2.装载JVM.dll
           3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例
           4.调用JNIEnv实例装载并处理class类。 

     java.exe创建JVM装载环境的时候会自动查找JRE,然后装入jvm.cfg([%JAVA_HOME%\jre|c:\Java\jre6]/lib/i386/jvm.cfg),而Java正是通过这个jvm.cfg配置文件来管理不同版本的JVM.dll的。通过这些文件我们可以定义目前JDK支持那些JVM,前面部分(client)是JVM名称,后面是参数: 

-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR	
KNOWN表示JVM存在,ALIASED_TO表示给别的JVM取一个别名,WARN表示不存在时找一个JVM替代,ERROR表示不存在抛出异常。

      Java通过LoadJavaVM来装入JVM.dll文件.动态连接库JVM.dll才是java虚拟机的实际操作处理所在,装入工作很简单就是调用Windows API函数:

             LoadLibrary装载JVM.dll动态连接库.然后把JVM.dll挂界到JNIENV(JNI调用接口)实例(把导出函数JNI_CreateJavaVM和 JNI_GetDefaultJavaVMInitArgs挂接到InvocationFunctions变量的CreateJavaVM和 GetDefaultJavaVMInitArgs函数指针变量)上。JVM.dll的装载工作宣告完成。

       调用InvocationFunctions->CreateJavaVM也就是JVM中JNI_CreateJavaVM方法获得JNIEnv结构的实例,然后就可以调用JNIEnv实例装载并处理class类。

       Java程序有两种方式(jar包和class文件)

             如果是执运行jar。 java -jar XXX.jar运行的时候,Java.exe调用GetMainClassName函数,该函数先获得JNIEnv实例然后调用Java类 Java.util.jar.JarFileJNIEnv中方法getManifest()并从返回的Manifest对象中取 getAttributes("Main-Class")的值,即jar包中文件:META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。之后main函数会调用java.c中LoadClass方法装载该主类(使用JNIEnv实例的FindClass)。main 函数直接调用java.c中LoadClass方法装载该类。 

           如果是执行class方法。main函数直接调用java.c中LoadClass方法装载该类。然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中
“publicstaticvoidmain(String[]args)”方法,并判断该方法是否为public方法,然后调用JNIEnv实例的CallStaticVoidMethod方法调用该Java类的main方法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值