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的更多相关文章

  1. 代码的坏味道(9)——异曲同工的类(Alternative Classes with Different Interfaces)

    坏味道--异曲同工的类(Alternative Classes with Different Interfaces) 特征 两个类中有着不同的函数,却在做着同一件事. 问题原因 这种情况往往是因为:创 ...

  2. eclipse中的classes文件夹同步问题

    问题: 在同步项目时,由于误操作将classes文件夹加入到了同步版本中,这样会导致每次更新程序编译后,会有很多class文件显示在同步清单中. 解决方案: 将classes文件不设置为同步. 1. ...

  3. Introduction of OpenCascade Foundation Classes

    Introduction of OpenCascade Foundation Classes Open CASCADE基础类简介 eryar@163.com 一.简介 1. 基础类概述 Foundat ...

  4. 6.Configure Domain Classes(配置领域类)【EF Code-First 系列】

    在前面的部分中,我们学习了Code-First默认约定,Code-First使用默认的约定,根据你的领域类,然后生成概念模型. Code-First模式,发起了一种编程模式:约定大于配置.这也就是说, ...

  5. app:clean classes Exception

    Error:Execution failed for task ':app:clean'.> Unable to delete directory: C:\Users\LiuZhen\Deskt ...

  6. Android framework编译出来的jar包classes.jar的位置

    在源码环境下编译 Android framework编译出来的jar包classes.jar的位置  out/target/common/obj/JAVA_LIBRARIES/framework_in ...

  7. yii 核心类classes.php详解(持续更新中...)

    classes.php在yii运行的时候将被自动加载,位于yii2文件夹底下. <?php /** * Yii core class map. * * This file is automati ...

  8. Top 15 Java Utility Classes

    In Java, a utility class is a class that defines a set of methods that perform common functions. Thi ...

  9. Eclipse下无法自动编译,或者WEB-INF/classes目录下没文件,编译失败的解决办法(转载)

    文章来源:http://www.cnblogs.com/xfiver/archive/2010/07/07/1772764.html 1.  IOException parsing XML docum ...

随机推荐

  1. pycharm多行代码缩进、左移

    在使用pycharm时,经常会需要多行代码同时缩进.左移,pycharm提供了快捷方式 1.pycharm使多行代码同时缩进 鼠标选中多行代码后,按下Tab键,一次缩进四个字符 2.pycharm使多 ...

  2. MySQL编码问题(无法插入中文)

    1.问题描述 2.解决方案 1.问题描述 当使用django时,如果数据库是MySQL,插入中文会报错: Incorrect string value: '\xF0\x9F...' for colum ...

  3. Python学习日记(一)——IDLE、运算符

    环境:win8.1+python2.7.8 一.名词解释: 1.IDLE:经常编程的同学相信对集成开发环境(Integrated Development Environment,IDE)应该非常熟悉了 ...

  4. python中的json的基本使用方法

    在python中使用json的时候,主要也就是使用json模块,json是以一种良好的格式来进行数据的交互,从而在很多时候,可以使用json数据格式作为程序之间的接口, #!/usr/bin/env ...

  5. Rhythmk 一步一步学 JAVA(11)Ibatis 环境配置

    1.项目文件分布. 2.example1.java: package com.rhythmk.example1; import java.io.IOException; import java.io. ...

  6. Visual Studio 进行Excel相关开发,Microsoft.Office.Interop.Excel.dll库

    1. Interop.Excel.dll 的查找 本文中将 Microsoft.Office.Interop.Excel.dll库简称为Interop.Excel.dll库 其实在使用Visual S ...

  7. PHP 数据集循环

    循环 $rs = $bbs->query("select top 10 * from tt"); while($row = $rs->fetch()) { //prin ...

  8. Django 学习之---缓存系统

    一.浏览器缓存机制 Cache-control策略(重点关注) Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务 ...

  9. Linux实战教学笔记54:开源虚拟化KVM(二)管理虚拟存储

    五,管理虚拟存储 5.1 虚拟磁盘概述 5.1.1 虚拟化项目中存储的注意事项 [x] 存储的性能几乎总是虚拟化的瓶颈 [x] 通过多个硬盘驱动以分布磁盘I/O来实现存储解决方案 [x] 考虑部署集中 ...

  10. cannot import name '_validate_lengths' from 'numpy.lib.arraypad'

    在Anaconda下新配置了tensorflow环境,结果在引入skimage 包时报错,错误提示from numpy.lib.arraypad import _validate_lengths,找不 ...