类加载程序如何加载方法内声明的扩展类实例?(java.lang.noclassdeffounderror)



我有一个具有UTIT功能的类,可以按需调用。

复制的步骤:

  1. testmainwebapp(该项目具有testmainimp的依赖性)
  2. testmainimpl(此项目实现testmaininterface)
  3. testmaininterface

testmainwebapp> testmainservlet.java

package com.main;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.test.util.Util;
/**
 * Servlet implementation class TestMainServlet
 */
@WebServlet("/TestMainServlet")
public class TestMainServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
         System.out.println("nCurrent ClassLoader chain: "+JavaEETrainingUtil.getCurrentClassloaderDetail());
         Util prov = new Util();
        // prov.test();
        }
}

testmainimpl> util.java&tlsorredirectListener.java

package com.test.util;
public class Util {
     private final static String CLAZZ = Util.class.getName();
    static {
            System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
     }
        public boolean checkForTLSErrorRedirection(boolean b) {                         
            test.intf.ConfigurationListener listener = new com.listener.TLSErrorRedirectListener();   
            listener.valueChanged("test", "test");
            return true;
        }    
public void test() {  
        System.out.println(" test util");  
    }
}

tlsorrediredirectionlistener.java

package com.listener;
import com.test.util.JavaEETrainingUtil;
public class TLSErrorRedirectListener implements test.intf.ConfigurationListener {
     final static String CLAZZ = TLSErrorRedirectListener.class.getName();
     static {
            System.out.println("Classloading of "+CLAZZ+" in progress..."+JavaEETrainingUtil.getCurrentClassloaderDetail());
     }
    public void valueChanged(String key, String value) {
        switch(key){
        case "test1": 
        default : break;
        }
    }
}

testmaininterface> configurationListener.java

package test.intf;
public abstract interface ConfigurationListener
{
  public abstract void valueChanged(String paramString1, String paramString2);
}

案例:

  1. testmaininterface.jar将在testmainimpl.jar的类中(仅@compiletime)
  2. 在运行时(我不会有testmaininterface.jar),并且我不调用" checkfortlsorredirectirection()"。我只调用test()方法。
  3. 但是我得到了,当我创建实例本身时。

您可以帮助找出根本原因吗?Java如何加载方法中声明的类?

注意: javaeetrainingutil.java 用于调试目的

package noclassdef.example1;
import java.util.Stack;
import java.lang.ClassLoader;
/**
 * JavaEETrainingUtil
 * @author Pierre-Hugues Charbonneau
 *
 */
public class JavaEETrainingUtil {
        /**
         * getCurrentClassloaderDetail
         * @return
         */
        public static String getCurrentClassloaderDetail() {
               StringBuffer classLoaderDetail = new StringBuffer();       
               Stack<ClassLoader> classLoaderStack = new Stack<ClassLoader>();
               ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
               classLoaderDetail.append("n-----------------------------------------------------------------n");
               // Build a Stack of the current ClassLoader chain
               while (currentClassLoader != null) {
                       classLoaderStack.push(currentClassLoader);
                       currentClassLoader = currentClassLoader.getParent();
               }
               // Print ClassLoader parent chain
               while(classLoaderStack.size() > 0) {
                       ClassLoader classLoader = classLoaderStack.pop();
                       // Print current                     
                       classLoaderDetail.append(classLoader);
                       if (classLoaderStack.size() > 0) {
                              classLoaderDetail.append("n--- delegation ---n");           } else {
                              classLoaderDetail.append(" **Current ClassLoader**");
                       }
               }
               classLoaderDetail.append("n-----n");
               return classLoaderDetail.toString();
        }
}

这是不正确的。您不应将abstract关键字添加到接口或其方法中。在接口方法上无需public;他们必须公开。

这是正确的:

package test.intf;
public interface ConfigurationListener {
  void valueChanged(String paramString1, String paramString2);
}

确保test.intf.ConfigurationListener.class文件出现在您的部署中。如果没有,则永远不会找到类。

最新更新