Java中classpath讲解及使用方式

笔者之前对于classpath都没有什么深入的研究,之前的项目打包jar包都是按照网上的教程自己照着葫芦画瓢。但是因为最近碰到一些关于这方面的知识,因此索性觉得要好好补充一下这方面的知识。下面的文章主要是翻译自oralce官网关于设置classpath的说明Setting the class path,并对其中一些地方进行了部分的补充说明,方便读者理解。

概要

classpath是Java运行时环境搜索类和其他资源文件(比如jar\zip等资源)的路径。可以通过JDK工具(比如javac命令、java命令)后面的-classpath 参数设置classpath(这个可以通过装有java环境的dos窗口下输入sdktool的命令来查看可以输入的参数选项,见下图)

或通过设置CLASSPATH环境变量。该 -classpath选项是首选项,因为您可以为每个应用程序单独设置,而不会影响其他应用程序,而无需其他应用程序修改其值。

下面是这两种方式的说明示例:

  • (1)通过jdk的命令行来为每个application设置

这个设置主要是为每个application设置,并不会影响别的程序的classpath以及环境变量的classpath,他只在当前窗口生效。

C:> sdkTool -classpath classpath1 ;classpath2 …

  • (2)设置classpath环境变量,这个是全局设置,对所有的应用程序生效

C:> set CLASSPATH=classpath1 ;classpath2 …

sdkTool

一个命令行工具,例如java, javac,javadoc,或apt。有关列表,请参阅JDK工具

classpath1 ;classpath2

.jar,.zip或.class文件的classpath。每个classpath应以文件名或目录结尾,针对不同的情况,设置classpath的格式方法如下:

  • (1)对于包含.class文件的.jar或.zip文件,classpath以.zip或.jar文件的名称结尾。

下面是示例,笔者自己将一个工程打包成jar包,同时指定这个jar包下的某个class文件运行。结果如下:

下面是工程的目录,其中工程中引用了其他jar包,笔者在打包的时候,用maven的assembly插件打包成了一个fat jar(想要了解具体打包方法,查看这两篇博文:

【Java】打包Jar包并用脚本执行

【Maven】Maven系列(二)——利用assembly插件打包

查看下面的classpath的值是怎么指定的。

  • (2)对于未命名包中的.class文件,classpath以包含.class文件的目录结束。比如一个a.class文件在d:path1\path2下,但是这个a.class没有package,那么如果想让jvm搜索到这个class文件,这时指定classpath的时候,可以使用d:path1\path2,因为classpath的默认路径是当前路径,因此在使用的时候,如果是在当前路径下打开dos窗口,classpath命令缺省,那么这个时候其效果与指定当前路径为classpath的效果等效。如下的示例:

test.java

public class test {
    public static void main(String[] args) {
        System.out.println("hello world!");
    }
}

这个类是没有package的。

下面是运行结果:

程序运行成功

  • (3)对于命名包中的.class文件,类路径以包含“root”包(完整包名称中的第一个包)的目录结束。

示例如下:

Equals.java在名为string的package下

package string;
public class Equals {
    public static void main(String[] args){
        String a=new String("test");
        String b=new String("test");
        System.out.println(a==b);
    }
}

那么对于这种情况,指定classpath的方式如下:

通过上面几条命令,可以看出来正确的命令行格式如下:

java -classpath package_rootpath package_name.class_name

多个路径条目以分号分隔。使用set命令,等号(=)周围的空格可以忽略。

默认classpath是当前目录。设置 CLASSPATH变量或使用 -classpath命令行选项将覆盖该默认值,因此,如果要在搜索路径中包含当前目录,则必须在新设置中包含“ . ”(关于路径的说明可以参考笔者的另一篇博文)。

既不是目录也不是归档(.zip或.jar文件)和*的classpath会被忽略。

描述

类路径告诉JDK工具和应用程序在哪里可以找到第三方和用户定义的类 - 即不是Java 扩展或Java平台的一部分的类。类路径需要找到你用javac编译器编译的任何类——其默认值是当前目录,以方便地找到这些类。

JDK,JVM和其他JDK工具通过按顺序搜索Java平台(bootstrap)类,任何扩展类和类路径来查找类。(有关搜索策略的详细信息,请参阅如何找到类。)大多数应用程序的类库都希望利用扩展机制。您只需要设置classpath,当您要加载的class满足下面的条件(a)不在当前目录或其任何子目录中的类时,(b)不在扩展机制指定的位置。

如果要从旧版本的JDK升级,启动设置可能包含CLASSPATH不再需要的设置。您应该删除任何不是特定于应用程序的设置,例如classes.zip。使用Java虚拟机的某些第三方应用程序可能会修改您的CLASSPATH环境变量以包含它们使用的库。这样的设置可以保持不变。

当您调用JVM或其他JDK工具或使用环境变量时,可以使用JDK工具’ -classpath选项来更改classpath。使用该选项优于设置环境变量,因为您可以为每个应用程序单独设置,而不会影响其他应用程序,而无需其他应用程序修改其值。

类可以存储在目录(文件夹)或归档文件(这里指的归档文件也就是那些jar包和zip包)中。Java平台类存储在 rt.jar。有关归档的更多详细信息以及有关类路径的工作原理的信息,请参阅本文档末尾附近的类路径和包名称。

重要说明:某些旧版本的JDK sofware 在默认的类路径中包含一个/classes条目。该目录存在供JDK软件使用,不应用于应用程序类。应用程序类应放在JDK等级目录之外。这样,安装新的JDK并不会强制您重新安装应用程序类。为了与旧版本兼容,使用/classes目录作为类库的应用程序 将以当前版本运行,但不保证将在以后的版本中运行。

使用JDK工具的-classpath选项

JDK工具java,jdb,javac和javah有一个-classpath选项,用于替换由classpath环境变量指定的路径 。这是改变classpath设置的推荐选项,因为每个应用程序都可以具有所需的classpath,而不会干扰任何其他应用程序。

运行时工具java也有一个 -cp选项。此选项是-classpath的缩写。

对于非常特殊的情况,java和 javac都有选项,可以让您更改用于查找自己的类库的路径。然而,绝大多数用户将永远不需要使用这些选项。

使用CLASSPATH环境变量

一般来说,您使用-classpath 命令行选项要像上一节介绍的那样。本节介绍如何设置CLASSPATH环境变量,或者清除以前安装中留下的设置。

设置CLASSPATH

在CLASSPATH环境变量修饰的组命令。格式为:

set CLASSPATH = path1 ; path2…

路径应以指定驱动器的字母开头,例如C:\。这样,如果您碰巧切换到其他驱动器,则仍然会找到class文件。(如果设置的路径是D:\,那么jvm就会去D盘下找这个class,而不是在C盘下)

清除CLASSPATH

如果您的CLASSPATH环境变量设置为不正确的值,或者您的启动文件或脚本设置不正确的路径,可以CLASSPATH 使用以下命令取消设置:

  C:> set CLASSPATH =

此命令仅在当前命令提示符窗口中取消CLASSPATH。您还应删除或修改启动设置,以确保CLASSPATH在将来的会话中拥有正确的设置。

更改启动设置

如果CLASSPATH变量在系统启动时设置,则要查找的位置取决于您的操作系统:

对于Windows 95和98,检查autoexec.bat的 set命令。

其他(Windows NT,Windows 2000,…) 的系统,CLASSPATH 环境变量可以使用控制面板中的系统实用程序来设定。

了解类路径通配符

类路径条目可包含基名通配符*,这被认为等同于指定在扩展目录下的所有文件的列表.jar或 .JAR。例如,类路径条目 foo/* 指的就是foo目录下的所有JAR文件。一个简单由*组成的类路径指的就是当前目录中所有jar文件的列表。

通配符*的classpath写法对于class文件来说不适用(意思就是通配符*适用的对象是jar而不是class)。要在单个目录中匹配类和JAR文件 foo,请使用foo;foo/*或 foo/*;foo。前者的顺序决定了foo文件目录下的类和资源加载在前,jar加载在后,后者反之亦然。

子目录不是递归搜索。例如, foo/*仅在查找JAR文件foo,而不包括foo/bar,foo/baz等子目录。

扩展类路径中枚举目录中的JAR文件的顺序未指定(The order in which the JAR files in a directory are enumerated in the expanded class path is not specified,这一句没看懂,读者如果有了解的,可以留言回复一下,谢谢!),并且可能因平台而异,甚至在同一台机器上也会随时变化。构建良好的应用程序不应取决于任何特定的顺序。如果需要特定的顺序,则JAR文件可以在类路径中显式枚举。

通配符的扩展这一过程是在调用程序的main方法之前,在类加载过程期间。每个包含通配符的输入类路径将被枚举为这个目录下的所有JAR文件路径。例如,如果目录foo包含 a.jar,b.jar和c.jar,然后将类路径foo/*扩展为 foo/a.jar;foo/b.jar;foo/c.jar,并且该字符串将是系统属性的值 java.class.path。

CLASSPATH环境变量和-classpath(或 -cp)的命令行选项没什么不同的。也就是说,通配符在所有情况下都是一样适用的。但是,类路径通配符在Class-Path jar-manifest头文件中并不符合要求(这一句话也不是很理解,希望读者指教!)。

了解类路径和包名称

Java类被组织成被映射到文件系统中的目录的包。但是,与文件系统不同,无论何时指定包名称,都可以指定整个 包名称,而不是它的一部分。例如,对于包名称 java.awt.Button是总是指定为 java.awt。

例如,假设您希望Java运行时可以找到Cool.class该类在utility.myapp包下。如果该目录的路径是 C:\java\MyClasses\utility\myapp,那么设置的classpath就应该包含C:\java\MyClasses。

要运行该应用程序,可以使用以下JVM命令:

C:> java -classpath C:\ java \ MyClasses utility.myapp.Cool

当应用程序运行时,JVM使用这个classpath设置来查找utility.myapp包中定义的任何其他类(也包括Cool类)。

请注意,命令中指定了整个包名称。如果是设置classpath为C:\java\MyClasses\utility并使用命令 java myapp.Cool,这种做法是不可能成功的。JVM找不到这个类。

(你可能想知道什么定义了一个类的包名称,答案是包名是类的一部分,不能修改,除了重新编译该类)。

注意:包指定机制的一个有趣的后果是,作为同一包的一部分的文件实际上可能存在于不同的目录中。每个类的包名称将相同,但是每个文件的路径可以从类路径中的不同目录开始。

文件夹和归档文件

当类存储在目录(文件夹)中时, 比如存储在c:\java\MyClasses\utility\myapp,那么classpath条目指向包含包名称的第一个元素的目录。也就是package的上一级目录(在这种情况下,classpath就是C:\java\MyClasses,因为包名是utility.myapp。)

但是当类存储在归档文件(.zip或.jar文件)中时,类路径条目是.zip或.jar文件的路径并包含.zip或.jar文件。例如,要使用.jar文件中的类库,命令将如下所示:

C:> java -classpath C:\ java \ MyClasses \ myclasses.jar utility.myapp.Cool

多重指定

要查找C:\java\MyClasses目录下的类以及C:\java\OtherClasses目录下的类,那么请将类路径设置为:

C:> java -classpath C:\ java \ MyClasses; C:\ java \ OtherClasses …

请注意,这两个路径以分号分隔。

指定顺序

多个classpath的顺序很重要。Java解释器将按照它们在classpath变量中出现的顺序来查找目录中的类。在上面的例子中,Java解释器将首先在C:\java\MyClasses目录下查找类。只有在该目录中找不到具有正确名称的类时,解释器才会在C:\java\OtherClasses 目录中查找。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于java类路径classpath和包的实例讲解

    类路径(classpath) java编译器编译.java文件和java虚拟机执行.class文件时的路径和写法不一样. 在没有设置任何classpath环境变量的情况下,javac可以编译全路径的.java文件.例如: javac d:\myjava\HelloWorld.java 编译后,在.java同路径目录下生成class文件. 默认java虚拟机要从classpath环境变量的路径中搜索class文件去执行,对于java虚拟机来说,这不是类文件,而是类.它只有类路径,而没有文件系统路径

  • JAVA获取CLASSPATH路径的方法详解

    ClassLoader 提供了两个方法用于从装载的类路径中取得资源: public URL getResource (String name); public InputStream getResourceAsStream (String name); 这里name是资源的类路径,它是相对与"/"根路径下的位置.getResource得到的是一个URL对象来定位资源,而getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据. 但是真正使用的不是Cl

  • 浅析JAVA_HOME,CLASSPATH和PATH的作用

    1,设置JAVA_HOME:一.为了方便引用,比如,你JDK安装在C:\ProgramFiles\Java\jdk1.7.0目录里,则设置JAVA_HOME为该目录路径, 那么以后你要使用这个路径的时候, 只需输入%JAVA_HOME%即可,避免每次引用都输入很长的路径串; 二.归一原则, 当你JDK路径被迫改变的时候, 你仅需更改JAVA_HOME的变量值即可, 否则,你就要更改任何用绝对路径引用JDK目录的文档, 要是万一你没有改全, 某个程序找不到JDK, 后果是可想而知的----系统崩溃

  • java环境变量path和classpath的配置

    在Java的学习中,涉及到两个系统环境变量path和classpath 一. path环境变量 path环境变量是系统环境变量的一种,它用于保存一系列的路径,每个路径之间用分号分隔.当在命令行窗口运行一个可执行文件时,操作系统首先会在当前目录下查找是否存在该文件,如果不存在会继续在path环境变量中定义的路径下寻找这个文件,如果仍未找到,系统会报错. 在Windows7系统下配置环境变量: 1.右击[计算机],选择[属性],出现如下界面: 图1 2.点击[高级系统设置],出现如下界面: 图2 3

  • java项目中classpath的理解

    在java项目中,你一定碰到过classpath,通常情况下,我们是用它来指定配置/资源文件的路径.在刚开始学习的时候,自己也糊里糊涂,但是现在,是时候弄清楚它到底是指什么了. 顾名思义,classpath就是class的path,也就是类文件(*.class的路径).一谈到文件的路径,我们就很有必要了解一个java项目(通常也是web项目)它在真正运行时候,这个项目内部的目录.文件的结构:这样,我们才好分析.理解classpath. 开发时期的web项目结构 下面,我以一个ssm的项目为例,我

  • java项目中classpath指向哪里

    今天在项目里看到好多地方都用到了classpath,并且自己对calsspath到底指向哪里还不是很清楚,所以就在网上百度了一下! 上面图片的意思简单来说,就是classpath只能表示lib目录和WEB-inf/classes路径下的文件,calsspath不能表示的src路径下面的文件, 但是从项目结构来看,配置文件一般是不放在放在WEB-INF下面啊,并且也没有看到classes路径,lib目录不是放依赖jar包的吗.此时感觉凉凉了.并且测试了一下,在WEB-INF路径下面创建了lib和c

  • java中Path和ClassPath用法比较

    java中Path是什么? 在计算机上安装Java后,需要设置PATH环境变量以便从任何目录方便地运行可执行文件(javac.exe,java.exe,javadoc.exe等),而无需键入完整路径命令.[视频教程推荐:Java教程] 例如: C:\ javac TestClass.java 否则,您需要在每次运行时指定完整路径,例如: C:\ Java \ jdk1.7.0 \ bin \ javac TestClass.java java中和ClassPath是什么? Classpath是J

  • Java中获取类路径classpath的简单方法(推荐)

    如下所示: <SPAN style="FONT-SIZE: 18px"> System.out.println("++++++++++++++++++++++++"); String path = System.getProperty("java.class.path"); String path2 = FreeMarkerWriter.class.getProtectionDomain().getCodeSource().getLo

  • Java中classpath讲解及使用方式

    笔者之前对于classpath都没有什么深入的研究,之前的项目打包jar包都是按照网上的教程自己照着葫芦画瓢.但是因为最近碰到一些关于这方面的知识,因此索性觉得要好好补充一下这方面的知识.下面的文章主要是翻译自oralce官网关于设置classpath的说明Setting the class path,并对其中一些地方进行了部分的补充说明,方便读者理解. 概要 classpath是Java运行时环境搜索类和其他资源文件(比如jar\zip等资源)的路径.可以通过JDK工具(比如javac命令.j

  • java中单例模式讲解

    目录 WHAT WHY HOW 饿汉式 实现一:静态实例参数与静态代码块 实现二:静态内部类 懒汉式 错误一:单线程实现 错误二:同步方法 错误三:同步代码块之单次检查 错误四:同步代码块之双重检查 正确:双重检查+阻止重排序 枚举 场景 个人认为单例模式是设计模式中最简单也是最常用的一种,是对有限资源合理利用的一种方式.这个模式看似简单,但是其中蕴含了关于并发.类加载.序列化等一系列深层次的知识,如果理解不够深,就有可能在高并发时遇到难以预期的异常,或者会造成资源浪费. 所以本文会从将目前Ja

  • 浅谈Java中的四种引用方式的区别

    强引用.软引用.弱引用.虚引用的概念 强引用(StrongReference) 强引用就是指在程序代码之中普遍存在的,比如下面这段代码中的object和str都是强引用: Object object = new Object(); String str = "hello"; 只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象. 比如下面这段代码: public class Main { publi

  • Java中的3种输入方式实现解析

    这篇文章主要介绍了Java中的3种输入方式实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.从键盘读取char类型数据 char ch = (char)System.in.read(); System.in 提供的 read() 方法每次只能读取一个字节的数据,所以用的频率比较低. 2.BufferedReader 实现从键盘读取String类型数据 使用BufferedReader 对象的 readLine() 方法必须处理 jav

  • Java中动态规则的实现方式示例详解

    背景 业务系统在应用过程中,有时候要处理"经常变化"的部分,这部分需求可能是"业务规则",也可能是"不同的数据处理逻辑",这部分动态规则的问题,往往需要可配置,并对性能和实时性有一定要求. Java不是解决动态层问题的理想语言,在实践中发现主要有以下几种方式可以实现: 表达式语言(expression language) 动态语言(dynamic/script language language),如Groovy 规则引擎(rule engine

  • 浅谈在Java中JSON的多种使用方式

    1. 常用的JSON转换 JSONObject 转 JSON 字符串 JSONObject json = new JSONObject(); jsonObject.put("name", "test"); String str = JSONObject.toJSONString(json); JSON字符串转JSON String str = "{\"name\":\"test\"}"; JSONObjec

  • 浅谈java中HashMap键的比较方式

    先看一个例子 Integer integer=12344; Integer integer1=12344; 在Java中Integer 和Integer1是不相等的,但是如果再执行如下语句 map.put(integer, 1); map.put(integer1, 2); 会发现2会把1覆盖,问题来了,明明是两个不同的对象,为什么,2会把1覆盖呢? 我们看HashMap中添加键的源代码,如下 可以发现我们传进来的键交给了一个hash的成员方法区处理,这里我们看看hash方法的源码 哦,看到这里

  • Java中创建对象的6种方式

    目录 背景 创建对象的 6 种方式 方法1:new 一个对象 方法2:克隆一个对象 方法3:类派发一个对象(反射) 方法4:动态加载一个对象(反射) 方法5:构造一个对象(反射) 方法6:反序列化一个对象 总结 背景 本文教你创建对象的 6 种方式,从低端到高端,各种创建方式,总有一个适合你,没有对象的自己生成一个吧! 创建对象的 6 种方式 假设有个女朋友类: @Data @NoArgsConstructor @AllArgsConstructor class GirlFriend { pri

  • Java中的final关键字使用方式

    目录 一.final概述 二.使用方式 修饰类 修饰方法 修饰变量 局部变量—引用类型 成员变量 一.final概述 子类可以在父类的基础上改写父类内容,比如,方法重写.那么我们能不能随意的继承API中提供的类,改写其内容呢?显然这是不合适的.为了避免这种随意改写的情况,Java提供了final 关键字,用于修饰不可改变内容.final: 不可改变.可以用于修饰类.方法和变量. 类:被修饰的类,不能被继承. 方法:被修饰的方法,不能被重写. 变量:被修饰的变量,不能被重新赋值. 二.使用方式 修

  • Java中BufferedReader和BufferedWriter使用方式

    目录 FileWriter/FileReader BufferedReader/BufferedWriter FileWriter/FileReader 介绍:FileWriter 类从 OutputStreamWriter 类继承而来.该类按字符向流中写入数据. 构造:参数为 File 对象 FileWriter(File file) 参数是文件的路径及文件名(默认是当前执行文件的路径) FileWrite(String filename) 等价于: OutputStreamWriter ou

随机推荐