在单独的classloader中隔离模块后,Spring IllegalAccessexception



我有一个问题,涉及Bouncycastle不兼容版本之间的JAR冲突。

我们通过创建一个bean,使用弹簧定义的classloader bean将其注入属性,从官方WEB-INF/lib文件夹中存储的类来解决它。

以下是豆定义

<bean id="metainfJarClassloader" class="com.jdotsoft.jarloader.JarClassLoaderFactory" factory-method="create"/>
<bean id="jadesFactory" class="it.csttech.proxy.jades.JadesFactory">
      <constructor-arg index="0" ref="metainfJarClassloader"/>       
</bean>
<bean id="bouncyCastleBeanFactory" class="it.csttech.proxy.bouncyCastle.BouncyCastleBeanFactory">
      <constructor-arg index="0" ref="metainfJarClassloader"/>       
</bean>

    <bean id="timestampService" class="it.csttech.pcp.services.spring.TimestampServiceImpl" lazy-init="true">
        <property name="timestampServerConfig">
            <bean factory-bean="jadesFactory" factory-method="createTSServerCfg">
            -------------------
            </bean>
        </property>
        <property name="jadesFactory" ref="jadesFactory" />
        <property name="bouncyCastleBeanFactory" ref="bouncyCastleBeanFactory" />
        <property name="jarClassLoader" ref="metainfJarClassloader" />
    </bean>

这是如何工作的?经过认证的时间戳服务是围绕在单独的jar中定义的服务的包装器,并通过使用metainfclassloader进行反射实例化。metainfclassloader服务加载在meta-inf/lib

下包含在罐子中的类

,例如

WEB-INF
  -- lib
    -- timestamp.jar (expanded below)
      -- META-INF
        -- lib
          -- it.infocert-jades-dts.jar
          -- org.bouncycastle-bcprov.jar
       -- src
          -- it/csttech/pcp/services/spring
             -- TimestampServiceImpl.java

timestampserviceimpl将从该元I-Inf目录中加载其依赖类。

我不明白的是为什么在启用了此组件后,仅通过懒惰的定义的认证时间戳服务来调用,我在春季获得了IllegalAccessError S的浓度。

具体来说,我无法访问MVC控制器中定义的任何private static class

证据:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.IllegalAccessError: it/package/NotificationsController$Dto
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:978) [spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) [spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [servlet-api.jar:?]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) [catalina.jar:8.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.39]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.39]
        at it.phoenix.web.context.PhoenixFilter.doFilter(PhoenixFilter.java:89) [phoenix-web-3.5.0.15.jar:17]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:8.0.39]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:8.0.39]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE]
------------
Caused by: java.lang.IllegalAccessError: it/package/NotificationController$Dto
        at it.phoenix.web.controllers.secure.common.NotificationsController$$FastClassBySpringCGLIB$$7a88e7c5.invoke(<generated>) ~[?:?]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
        at it.phoenix.web.controllers.secure.common.NotificationsController$$EnhancerBySpringCGLIB$$5c5467a.scrollBottom(<generated>) ~[phoenix-web-3.5.0.15.jar:17]

问题的第1部分

那是什么意思?我总是通过将private static放置在我的MVC控制器类中定义DTO,并且它总是起作用

问题的第2部分

我看不到JarClassLoader实际上参与加载控制器类。Spring Main Class Loader(或使用该类加载程序(找到任何bean of类型ClassLoader

是否会增强自身(

这不是Spring本身或我的代码的问题,但是Jarclassloader本身有问题。虽然有据可理解和可理解的文献,但以下行是罪魁祸首

    Thread.currentThread().setContextClassLoader(this); //loadClass method

分析

作者的分析是正确的,因为jarclassloader 必须是当前线程的主要classloader。从JAR资源加载类后,该类 May 由于反射而加载其他类,或仅仅是因为它提供了引用其他类的服务。那么,谁可以重复加载新课程?jarclassloader当然。

,但是春季存在问题,我仍然认为它令人难以置信。Spring并不关心自定义类加载器Bean,而是ContextLoader类关心当前线程,以在线程和上下文之间创建映射。可能是因为春天想隔离不同的上下文。Kudos!

最终调试春天,我发现了奇数。上下文映射具有Jarclassloader,而不是Tomcat的主要URLClassLoader

解决方案

修改Jdotsoft提供的JARCLASSLOADER,以便在实例化课后还原原始的类加载程序。如果依靠依赖类的类的类希望从线程使用类Loader而不是从getClass()

使用类的类,这可能不会阻止进一步的错误。
    Thread.currentThread().setContextClassLoader(this);

变成

    ClassLoader old = Thread.currentThread().getContextClassLoader();
    Thread.currentThread().setContextClassLoader(this);
    try {
    ---------
    } finally {
        Thread.currentThread().setContextClassLoader(old);
    }

最新更新