Why won't JRockit find my classes
This is the second post by Mattis, diving deep into JVM specifics. NoClassDefFoundErrors are a drag. The classloader mechanism in the Java specification is very powerful, but it also gives you plenty of ways to mess things up. In which jar did you put that class file, and why isn't your classloader looking in that jar? In rare cases, you might even have an application that works using Sun Java, but throws a NoClassDefFoundError with JRockit. Surely, this must be a JRockit bug? Not necessarily. There is a slight difference in how the two JVMs work that can explain this behaviour, especially if you modify your classloaders during runtime. Let's take an example: In a separate folder "foo", create a file Foo.java:
public class Foo {
public Foo () {
System.out.println("Foo created");
}
}
Now, in your root folder for this experiment, create the file ClasspathTest.java:
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method; public class ClasspathTest {
private static final Class[] parameters = new Class[]{URL.class}; // Adds a URL to the classpath (by some dubious means)
// method.setAccessible(true) is not the trademark of good code
public static void addURL(URL u) throws Exception {
Method method = URLClassLoader.class.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke((URLClassLoader) ClassLoader.getSystemClassLoader(), new Object[]{u});
} public static void main(String[] arg) throws Exception{
// Add foo to the classpath, then create a Foo object
addURL(new File("foo").toURL());
Foo a = new Foo();
}
}
This class has a method "addURL" that basically adds a URL to the classpath of the system classloader. The main method uses this method to first add the folder "foo" to the classpath and then creates a Foo object. When you compile this method, add "foo" to the classpath:
> javac -classpath .;foo Test.java
But when you run the program, don't add foo, simply run
> java Test
Using Sun Java, this will work fine. In the first line of main, we add the foo-folder to the classpath. When we create our first Foo-object, we find the Foo class in the foo folder. Using JRockit however, you get:
Exception in thread "Main Thread" java.lang.NoClassDefFoundError: Foo
at ClasspathTest.main(ClasspathTest.java:20)
To understand this behaviour, you have to first understand how Sun and JRockit runs code. Sun Java is an interpreting JVM. This means that the first time you run a method, the JVM will interpret every line step by step. Therefore, Sun will first interpret and run the first line of main, adding "foo" to the classpath, and then the second line, creating the Foo object. JRockit however uses another strategy. The first time a method is run, the entire method is compiled into machine code. To do this, all classes used in the method needs to be resolved first. Therefore, JRockit tries to find the Foo class BEFORE the "foo" folder is added to the classpath, resulting in the NoClassDefFoundError (still thrown just before trying to use the class). So, who is right? Actually, according to the Java spec, both are. Resolving the classes can be done either right before the class is used or as early as during method invocation. For most developers, this is just trivia, but from time to time we see problems with this from customers. The solution? Don't modify your classloaders in the same method as you need the change to load a class. In the example, the following change works fine in both Sun and JRockit:
public static void main(String[] arg) throws Exception{
// Add foo to the classpath, then create a Foo object in another method
addURL(new File("foo").toURL());
useFoo();
}
public static void useFoo() {
Foo a = new Foo();
}
Here, using JRockit, the class is not resolved until the method useFoo is compiled, which will be AFTER "foo" is added to the classpath. /Mattis PS: Adding URLs to the system classloader during runtime might not be a good idea. But when using your own defined classloaders, modifying these during runtime could very well be according to design.
Why won't JRockit find my classes的更多相关文章
- 代码的坏味道(9)——异曲同工的类(Alternative Classes with Different Interfaces)
坏味道--异曲同工的类(Alternative Classes with Different Interfaces) 特征 两个类中有着不同的函数,却在做着同一件事. 问题原因 这种情况往往是因为:创 ...
- eclipse中的classes文件夹同步问题
问题: 在同步项目时,由于误操作将classes文件夹加入到了同步版本中,这样会导致每次更新程序编译后,会有很多class文件显示在同步清单中. 解决方案: 将classes文件不设置为同步. 1. ...
- Introduction of OpenCascade Foundation Classes
Introduction of OpenCascade Foundation Classes Open CASCADE基础类简介 eryar@163.com 一.简介 1. 基础类概述 Foundat ...
- 6.Configure Domain Classes(配置领域类)【EF Code-First 系列】
在前面的部分中,我们学习了Code-First默认约定,Code-First使用默认的约定,根据你的领域类,然后生成概念模型. Code-First模式,发起了一种编程模式:约定大于配置.这也就是说, ...
- app:clean classes Exception
Error:Execution failed for task ':app:clean'.> Unable to delete directory: C:\Users\LiuZhen\Deskt ...
- Android framework编译出来的jar包classes.jar的位置
在源码环境下编译 Android framework编译出来的jar包classes.jar的位置 out/target/common/obj/JAVA_LIBRARIES/framework_in ...
- yii 核心类classes.php详解(持续更新中...)
classes.php在yii运行的时候将被自动加载,位于yii2文件夹底下. <?php /** * Yii core class map. * * This file is automati ...
- Top 15 Java Utility Classes
In Java, a utility class is a class that defines a set of methods that perform common functions. Thi ...
- Eclipse下无法自动编译,或者WEB-INF/classes目录下没文件,编译失败的解决办法(转载)
文章来源:http://www.cnblogs.com/xfiver/archive/2010/07/07/1772764.html 1. IOException parsing XML docum ...
随机推荐
- java类继承总结一 父类类型与子类类型之间的转化问题(转)
java类继承总结一 父类类型与子类类型之间的转化问题 本文将通过一个实例描述父类类型与子类类型之间的转化问题,这个很特殊的问题常常会导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂 ...
- Python添加模块
参考博客:http://blog.csdn.net/damotiansheng/article/details/43916881 http://my.oschina.net/leejun2005/bl ...
- linux中find工具
find 由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下.即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只要你具有相应的权限. ...
- how to use jquery with primefaces
PrimeFaces already ships with jQuery bundled, yet you've downloaded and installed another one which ...
- Python的输入输出
一:Python2.x版本下的输入输出 Python2.x 下的输入 1)raw_input 格式:result = raw_input("提示信息")功能:1)会等待用户输入内容 ...
- 出现The folder is already a source folder
右键build path -> configure build path -> source ,选择 src/main/java.src/test/java删除,然后再新建.
- shell编程——日志输出的同时显屏
在执行脚本的时候我们常常需要将执行过程全部输出到日志里,以备出现报错时可以跟踪分析,开始我用的是exec: exec 1>info.log #把全部执行过程输出到info日志中 exec 2&g ...
- 在MyEclipse中用debug调试应用程序
F5:单步测试,作用是跳入,比如说一大步中分为10小步,单击F5一次就会走完一小步,走完这一大步则需要单步10次.F6:与F5一样也是单步测试.只不过与F5不同的是F5追求的是过程,而F6追求的是结果 ...
- spring与IOC,ioc与di的关系
- Vertex Lit
[Vertex Lit] Vertex Lit path generally renders each object in one pass, with lighting from all light ...