`
sw1982
  • 浏览: 511405 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Eclipse plugin开发中的ClassNotFoundException问题

阅读更多

一 .关于classloader的一些悲剧

加载顺序:parent-first 跟child-first

 说起classloader,就不得不提到这么一篇文章了“Taxonomy of class loader problems encountered when using Jakarta Commons Logging “,by Ceki Gülcü,也就是 log4j跟logback的作者。 这是一篇谈common logging在类加载上的问题。 整个示例及文章可以在这里下载到:http://articles.qos.ch/delegation/cl-problems.zip (附件也放了一份),强烈推荐下载了研究一下里面的demo

1.parent-first(

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When called upon to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the bootstrap class loader, does not itself have a parent but may serve as the parent of a ClassLoader instance.

Thus, parent-first delegation is the default and recommended delegation model in Java.

)

 也就是说,在加载一个类的时候,会通过代理模式去寻找类的parent,并由上而下的顺序进行加载,这种父到子的类加载方式是jdk推荐+默认的。 注意,是默认的。

 

2.child-first(

a child class loader may prefer to first attempt to load resources on its own, and only later to delegate to its parent. We refer to this kind of class loaders as following the child-first delegation model. Note that the Servlet Specification only recommends child-first delegation order. In practice, not all Servlet Containers implement the child-first delegation model. Both delegation models are fairly common in practice.)

这里需要注意的是。。Servlet规范只将child-first作为唯一类加载顺序。

二。Elipse插件访问project的NoClassDefFoundError错误

在eclipse插件开发中只有一种次序的parent-first class loader,但是开发过程中同样会碰到NoClassDefFoundError ,那么是什么其他原因呢?

 

目标 :“代码生成插件”---选中某个IJavaProject的一个*.java,用ftl模板生成文件,

 

在同一个java项目里面,我们通常使用Class.forName这样的代码来加载class

try {
    Class clz = Class.forName("weisong.AbcAction"); //
    System.out.println(clz);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

,但是这行代码在plugin项目中行不通。。。因为Eclipse自身每个plugin会有自己的类加载器,

并且有自己独特的插件依赖关系定义机制,OS系统的cp变量对其无效!  这里的加载失败不是有序顺序先后导致,而是cp问题,

 

于是在插件代码实现了一个helper类,来解决插件项目访问workspace项目资源的功能: 整个代码最核心的地方就是

将不同loader 的classpath属性进行复制( 类定义如果不在cp里面,当然是加载不到的)

/**
 * 用来加载eclipse workspace里面java项目的class辅助classloader
 * Class Helper to load class of java project.
 */
public final class ClassHelper {

    private static final String PROTOCAL_PREFIX = "file:///";

    /**
     * get the <code>ClassLoader</code> of java project specified.
     *
     * @param project <code>IJavaProject</code>
     * @return <code>ClassLoader</code> of java project
     * @throws CoreException
     * @throws MalformedURLException
     */
    public static ClassLoader getProjectClassLoader(IJavaProject project)
            throws CoreException,MalformedURLException {

        //compute the project classpaths
        //REVIEW: Are the classpaths returned by computeDefaultRuntimeClassPath enough to load class?
        String[] classPaths = JavaRuntime.computeDefaultRuntimeClassPath(project);

        URL[] urls = new URL[classPaths.length];
        for (int i = 0; i < classPaths.length; i++) {
                urls[i] = new URL(PROTOCAL_PREFIX + computeForURLClassLoader(classPaths[i]));
        }
        return new URLClassLoader(urls);
    }

    /**
     * load <code>Class</code> in java project
     *
     * @param project <code>IJavaProject</code>
     * @param className name of class to load
     * @return <code>Class</code>
     * @throws ClassNotFoundException
     * @throws CoreException
     * @throws MalformedURLException
     */
    public static Class loadClass(IJavaProject project, String className)
            throws CoreException, ClassNotFoundException,MalformedURLException {
        ClassLoader loader = getProjectClassLoader(project);
        Class clazz = loader.loadClass(className);
        loader = null;
        return clazz;
    }

    /**
     * transform the <code>IType</code> to <code>Class</code>
     *
     * @param type <code>IType</code>
     * @return <code>Class</code>
     * @throws ClassNotFoundException
     * @throws MalformedURLException
     */
    public static Class typeToClass(IType type) throws CoreException,
            ClassNotFoundException,MalformedURLException {
        try {
            if (null != type && (type.isClass() || type.isInterface())) {
                String className = type.getFullyQualifiedName('$');
                return loadClass(type.getJavaProject(), className);
            }
        } catch (JavaModelException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * because of URLClassLoader assumes any URL not ends with '/' to refer to a
     * jar file. so we need to append '/' to classpath if it is a folder but not
     * ends with '/'.
     *
     * @param classpath
     * @return
     */
    private static String computeForURLClassLoader(String classpath) {
        if (!classpath.endsWith("/")) {
            File file = new File(classpath);
            if (file.exists() && file.isDirectory()) {
                classpath = classpath.concat("/");
            }
        }
        return classpath;
    }
}

 

到这里就明白了。。classloader除了不同的实现,还必须注意其classpath属性:)

 

 

另外,plugin项目如果要访问本项目自身的资源,可以这么来

//plugin项目本身路径:
String location = Platform.getBundle("API_GEN").getLocation();//"reference:file:/E:/ws1/API_GEN/"
//去掉""reference:file:/"
location = (String) location.subSequence(16, location.length());  // "E:/ws1/API_GEN/"

 

 

  • 大小: 46.7 KB
分享到:
评论
4 楼 svygh123 2014-01-16  
请问我现在做一个编辑器插件,怎么调用getProjectClassLoader(IJavaProject project)来获取ClassLoader呢,不知道怎么在编辑器中获取IJavaProject
3 楼 svygh123 2014-01-16  
在plugin.xml的Dependencies中,Required Plug-ins下引用org.eclipse.jdt.launching即可找到JavaRuntime
2 楼 svygh123 2014-01-16  
请问第一段代码里面的JavaRuntime是哪个包下的呢?
1 楼 adminfxing 2010-12-22  
谢谢...终于解决我的问题了!

相关推荐

    fatjar 打包插件与快速查找eclipse插件

    在Java开发环境中,打包应用程序通常是一项重要的任务,而`fatjar`工具或插件就是解决这一问题的一个解决方案。`fatjar`允许开发者将所有的依赖库和源代码打包成一个独立的JAR(Java Archive)文件,使得用户可以...

    Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.Transformer异常

    在Maven中,你可以使用`maven-assembly-plugin`或`maven-shade-plugin`来聚合所有依赖到单个可执行JAR中。 4. **IDE配置**:如果你使用的是集成开发环境,检查项目的构建路径设置,确保所有必要的库都被包含在构建...

    maven安装手册

    - 在`links`目录下创建一个名为`maven.link`的文件,内容为指向Maven插件的路径(例如:`path=e:\eclipse4.3.1\Myplugins\eclipse-maven-plugin-3.x.x`)。 通过以上步骤,Maven将在Eclipse或Myeclipse中成功安装...

    maven错误积累

    1. **DescriptionResource Path Location Type Project configuration is not up-to-date with pom.xml**:这个问题意味着Eclipse中的项目配置没有与pom.xml同步。解决方法是在Maven菜单中选择【Update Project ...

    nutch安装开发环境的配置

    在安装和配置 Nutch 开发环境时,可能会遇到各种问题,以下是对这些问题的详细解答。 首先,确保你已经下载了 Nutch 的正确版本。Nutch 的官方网站可能只提供最新的稳定版本,如 1.6 或 2.1。如果需要其他版本,...

    java解决org.springframework.web.context.ContextLoaderListener

    在Java Web开发中,`org.springframework.web.context.ContextLoaderListener` 是Spring框架的一部分,它负责初始化一个Web应用程序的Spring上下文。这个监听器是基于Servlet容器(如Tomcat、Jetty等)的,当Web应用...

    net.sf.fjep.fatjar_0.0.23

    Fatjar插件的工作原理是将项目及其所有依赖的第三方库合并到一个JAR文件中,这样当用户运行这个JAR时,所有必要的类和资源都已包含在内,避免了“ClassNotFoundException”和其他由于找不到依赖导致的问题。...

    maven文档资料

    - 如果在Maven项目中遇到`ClassNotFoundException`,即使POM.xml中已经声明了依赖,可能是因为Maven没有正确下载或解析依赖。解决方法包括清理并重新构建项目(`mvn clean && mvn install`),检查Maven的本地仓库...

Global site tag (gtag.js) - Google Analytics