读书人

对clazz.getResource(quot;quot;)的困惑请朋

发布时间: 2011-12-14 23:20:17 作者: rapoo

对clazz.getResource("")的困惑,请朋友们解惑,谢谢!
节约时间,开门见山,不嗦了,看代码:
有两个jar包(必须打jar包来分析)
cl1.jar只要一个类外加一个没用内容的test.txt文件位于test包下

Java code
package test;public class A {}

cl2.jar只要一个类
Java code
package test;public class Main {    public static void println(Class clazz) {        System.out.println("=====" + clazz.getName() + "=====");        try {            System.out.println("1 " + clazz.getResource(""));        } catch (Exception e) {            System.out.println("1 error " + e.getMessage());        }        try {            System.out.println("2 " + clazz.getResource("/"));        } catch (Exception e) {            System.out.println("2 error " + e.getMessage());        }        try {            System.out.println("3 " + clazz.getClassLoader().getResource(""));        } catch (Exception e) {            System.out.println("3 error " + e.getMessage());        }        System.out.println("4 " + clazz.getResource("test.txt"));    }    public static void main(String[] args) {        println(Main.class);        try {            println(Class.forName("test.A"));        } catch (ClassNotFoundException e) {            System.out.println("ClassNotFound " + e.getMessage());        } catch (Exception e) {            e.printStackTrace();        }        try {            println(Class.forName("oracle.jdbc.driver.OracleDriver"));        } catch (ClassNotFoundException e) {            System.out.println("ClassNotFound" + e.getMessage());        } catch (Exception e) {            e.printStackTrace();        }    }}


批处理
BatchFile code
@set CLASSPATH=.;%CLASSPATH%;cl1.jar;ojdbc14_g.jar;@ECHO java -jar cl2.jar调用**************************************************@java -jar cl2.jar@ECHO 将cl2.jar添加到CLASSPATH中@set CLASSPATH=.;%CLASSPATH%;cl2.jar;@ECHO java test.Main调用**************************************************@java test.Mainpause

输出
java -jar cl2.jar调用**************************************************
=====test.Main=====
1 null
2 null
3 null
4 null
ClassNotFound test.A
ClassNotFoundoracle.jdbc.driver.OracleDriver
将cl2.jar添加到CLASSPATH中
java test.Main调用**************************************************
=====test.Main=====
1 null
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
4 jar:file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/cl1.jar!/test/test.txt
=====test.A=====
1 null
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
4 jar:file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/cl1.jar!/test/test.txt
=====oracle.jdbc.driver.OracleDriver=====
1 jar:file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/ojdbc14_g.jar!/oracle/jdbc/driver/
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/
4 null



不打jar包输出,eclipse测试的,没有在cmd中测试,但是在cmd下结果应该一致。
=====test.Main=====
1 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/test/
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
4 jar:file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl1/cl1.jar!/test/test.txt
=====test.A=====
1 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/test/
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
4 jar:file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl1/cl1.jar!/test/test.txt


=====oracle.jdbc.driver.OracleDriver=====
1 jar:file:/D:/SYJ.WORK/SYJ.LIB/driver/oracle-connector/ojdbc14_g.jar!/oracle/jdbc/driver/
2 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
3 file:/D:/SYJ.WORK/SYJ.WORKSPACE/ws1/cl2/bin/
4 null



[解决办法]
先帮顶一个
[解决办法]
你都是在 Eclipse 的 Export 下进行打包的吧。

你用 Ant 或者 jar 工具进行打包,看看结果是不是这样呢?

下面是我用 Ant 打包,之后运行那个 bat 的结果(注:我用的是 MySql 的 JDBC 驱动):

Java code
java -jar cl2.jar调用**************************************************D:\test=====test.Main=====1 jar:file:/D:/test/cl2.jar!/test/2 null3 null4 nullD:\test=====com.mysql.jdbc.Driver=====1 jar:file:/D:/test/mysql-connector-java-5.1.5-bin.jar!/com/mysql/jdbc/2 null3 null4 nullD:\test=====com.bao.A=====1 jar:file:/D:/test/cl1.jar!/com/bao/2 null3 null4 jar:file:/D:/test/cl1.jar!/com/bao/test.txt将cl2.jar添加到CLASSPATH中java test.Main调用**************************************************D:\test=====test.Main=====1 jar:file:/D:/test/cl2.jar!/test/2 file:/D:/test/3 file:/D:/test/4 nullD:\test=====com.mysql.jdbc.Driver=====1 jar:file:/D:/test/mysql-connector-java-5.1.5-bin.jar!/com/mysql/jdbc/2 file:/D:/test/3 file:/D:/test/4 nullD:\test=====com.bao.A=====1 jar:file:/D:/test/cl1.jar!/com/bao/2 file:/D:/test/3 file:/D:/test/4 jar:file:/D:/test/cl1.jar!/com/bao/test.txt
[解决办法]
超出我的理解范围了
[解决办法]
关注一下
[解决办法]
public static void main(String[] args) {
println(Main.class);
System.out.println("---------------------");
println(test.Main.class);

运行了一下:
打包jar:
E:\workspace1\t11\bin>java -jar c12.jar
=====test.Main=====
1 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/
2 null
3 null
4 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/test.txt
---------------------
=====test.Main=====
1 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/
2 null
3 null
4 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/test.txt
=====test.A=====
1 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/
2 null
3 null
4 jar:file:/E:/workspace1/t11/bin/c12.jar!/test/test.txt
ClassNotFound :oracle.jdbc.driver.OracleDriver

eclipse :
=====test.Main=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
---------------------
=====test.Main=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
=====test.A=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
ClassNotFound :oracle.jdbc.driver.OracleDriver

cmd下运行:
E:\workspace1\t11\bin>java test.Main
=====test.Main=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
---------------------
=====test.Main=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
=====test.A=====
1 file:/E:/workspace1/t11/bin/test/
2 file:/E:/workspace1/t11/bin/
3 file:/E:/workspace1/t11/bin/
4 file:/E:/workspace1/t11/bin/test/test.txt
ClassNotFound :oracle.jdbc.driver.OracleDriver



[解决办法]
我去看了看oralce的驱动

除了MANIFEST.MF不同外

有看了你所说的那个static代码块,贴出来给你看一下
OracleDriver类中的:
static
{
m_driverAccess = new Properties();
m_driverAccess.put("thin-server", "oracle.jdbc.thinserver.ServerTTC7Protocol");
m_driverAccess.put("oci-server", "oracle.jdbc.ociserver.ServerOCIDBAccess");
m_driverAccess.put("thin", "oracle.jdbc.ttc7.TTC7Protocol");
m_driverAccess.put("oci8", "oracle.jdbc.oci8.OCIDBAccess");
m_driverAccess.put("oci", "oracle.jdbc.oci8.OCIDBAccess");
m_driverAccess.put("kprb", "oracle.jdbc.kprb.KprbDBAccess");
m_defaultDriver = null;
Timestamp timestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
try
{
if(m_defaultDriver == null)
{
m_defaultDriver = new OracleDriver();
DriverManager.registerDriver(m_defaultDriver);
}
}
catch(RuntimeException runtimeexception) { }
catch(SQLException sqlexception) { }
}


m_defaultDriver = new OracleDriver(); 他这里有new了一个对象




[解决办法]
果然都是高手.
纯学习.
帮顶..............
[解决办法]
关注下,研究研究!
[解决办法]
因为我懒得去具体一个一个测试了,所以大家尽量领会精神,如果写出错来了,一定要狠狠拍我。

有了classpath,再看getResource()是怎么去classpath里找的

比如System.out.println("1 " + clazz.getResource(""));

意思,就是从先找到clazz所在的包,然后返回这个包,里的名字是""的资源。

同志,同志,注意啦。
要是文件系统,""还可以翻译成当前包的目录。
要是jar文件。你这个东西""返回是啥资源。jar里又不能当目录用。当然就是null了。这还有啥问题?

搞明白了这个就简单了。
下面的因为可以找到classpath的file:目录,所以当然就返回目录了。
[解决办法]

探讨
我的真实需求是无论在多么复杂的情况(复杂的类加载环境)下我需要知道当前类所在的jar文件。

[解决办法]
我的真实需求是无论在多么复杂的情况(复杂的类加载环境)下我需要知道当前类所在的jar文件。
这个需求源于
http://topic.csdn.net/u/20080518/23/c2fb1b90-4e21-46a9-a756-f0309c57f952.html
但是现在我遇到的问题确实解决不了。

楼主,我也极度想知道这个问题的解答答案,UP上去
[解决办法]
用过这个,this.getClass().getClassLoader().getResource("")

[解决办法]
恩恩,我也正想搞明白这个问题!
学习了。
[解决办法]
想到了就做!

刚刚做了一个试验,证实了上一贴的猜测,确实是 jar 包本身的问题:folder 也可以作为 entry 存在,而是否有这样的 entry 就直接影响了 getResource("") 的结果。

至于如何把 folder 加到 jar 中去,看你用什么做打包工具了,我用的是 Eclipse 的 Export/JAR file 功能,里面直接就有这个选项。

如果想看生成的 jar 包里是否有 folder 形式的 entry,可以用下面这个命令:

jar -tvf test.jar

至此,LZ 的问题应该算是有个完美的解释了吧 ^_^
[解决办法]
回复
[解决办法]

[解决办法]
呵呵,学到不少东西,
[解决办法]
没有研究过楼主的问题,只知道实现具体的程序
------解决方案--------------------


继续学习...

[解决办法]

探讨
果然都是高手.
纯学习.
帮顶..............

[解决办法]


再来学习一下,顺便帮顶~
[解决办法]
up
[解决办法]
真是佩服各位的钻研精神
学习了
[解决办法]
查找带有给定名称的资源。查找与给定类相关的资源的规则是通过定义类的 class loader 实现的。此方法委托给此对象的类加载器。如果此对象通过引导类加载器加载,则此方法将委托给 ClassLoader.getSystemResource(java.lang.String)。
[解决办法]
来晚了,先帮忙顶帖!
[解决办法]
有收获,顶下
不过我觉得xyz20003没有什么不好的意思,语气轻松,带点调侃而已,
[解决办法]
很遗憾,我没看懂……

偶会好好学习的!
[解决办法]
呵呵..我是见到牛人了.我对里面的牛人不发表任何看法.学习ing..帮顶.好贴呀...
[解决办法]
再学习..我试着拿LZ的代码在机上运行.可是出来下面的结果
Java code
=====Test.Main=====1 file:/G:/alking/test/build/classes/Test/2 file:/G:/alking/test/build/classes/3 file:/G:/alking/test/build/classes/4 nullException in thread "main" java.lang.NoClassDefFoundError: test/A (wrong name: Test/A)        at java.lang.ClassLoader.defineClass1(Native Method)        at java.lang.ClassLoader.defineClass(ClassLoader.java:620)        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)        at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)        at java.net.URLClassLoader.access$000(URLClassLoader.java:56)        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)        at java.security.AccessController.doPrivileged(Native Method)        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)        at java.lang.Class.forName0(Native Method)        at java.lang.Class.forName(Class.java:169)        at Test.Main.main(Main.java:40)Java Result: 1
[解决办法]
关注一下
[解决办法]
在我本机上的测试结果:
Java code
java -jar cl2.jar调用**************************************************[color=#FF6600]Failed to load Main-Class manifest attribute fromcl2.jar[/color]将cl2.jar添加到CLASSPATH中java csdn.clazz.cl2.Main调用**************************************************=====wxxr.csdn.clazz.cl2.Main=====1 jar:file:/G:/clazz/cl2.jar!/wxxr/csdn/clazz/cl2/2 file:/G:/clazz/3 file:/G:/clazz/4 null=====wxxr.csdn.clazz.cl1.A=====1 jar:file:/G:/clazz/cl1.jar!/wxxr/csdn/clazz/cl1/2 file:/G:/clazz/3 file:/G:/clazz/4 jar:file:/G:/clazz/cl1.jar!/wxxr/csdn/clazz/cl1/test.txt=====org.gjt.mm.mysql.Driver=====1 jar:file:/G:/clazz/mysql-connector-java-3.1.13-bin.jar!/org/gjt/mm/mysql/2 file:/G:/clazz/3 file:/G:/clazz/4 nullG:\clazz>pause
[解决办法]
标签不能嵌套使用……
Failed to load Main-Class manifest attribute from
cl2.jar
这句是什么意思呢?
------解决方案--------------------


刚才看到我的包名错了..呵呵..现在的结果

Java code
=====Test.Main=====1 file:/G:/alking/test/build/classes/Test/2 file:/G:/alking/test/build/classes/3 file:/G:/alking/test/build/classes/4 null=====Test.A=====1 file:/G:/alking/test/build/classes/Test/2 file:/G:/alking/test/build/classes/3 file:/G:/alking/test/build/classes/4 nullClassNotFoundoracle.jdbc.driver.OracleDriver
[解决办法]
好贴,顶下!
[解决办法]
先学习...

读书人网 >J2SE开发

热点推荐