java - 如何使用 Javassist 进行字节码操作以解决链接错误?

标签 java spring instrumentation javassist

我发布了几个与javassit链接错误相关的问题spring Exception when running application on WebSphere with java 8 。现在,经过围绕此主题和错误的一些研究工作,我获得了一些有关使用 Javassist 进行字节码操作以解决链接错误的有用信息。

供您引用(已在此处的其他问题中发布此堆栈跟踪)

  [10/13/17 ] 00000089 webapp        E com.ibm.ws.webcontainer.webapp.WebApp logServletError SRVE0293E: [Servlet                                                                       Error]-[weblge]: java.lang.ExceptionInInitializerError
        at java.lang.J9VMInternals.ensureError(J9VMInternals.java:134)
        at java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:123)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:83)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:57)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:437)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:120)
        at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:345)
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:278)
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:103)
        at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1826)
        at com.ibm.ws.webcontainer.webapp.WebAppImpl.initialize(WebAppImpl.java:442)
        at com.ibm.ws.webcontainer.webapp.WebGroupImpl.addWebApplication(WebGroupImpl.java:88)
        at com.ibm.ws.webcontainer.VirtualHostImpl.addWebApplication(VirtualHostImpl.java:171)
        at com.ibm.ws.webcontainer.WSWebContainer.addWebApp(WSWebContainer.java:904)
        at com.ibm.ws.webcontainer.WSWebContainer.addWebApplication(WSWebContainer.java:789)
        at com.ibm.ws.webcontainer.component.WebContainerImpl.install(WebContainerImpl.java:427)
        at com.ibm.ws.webcontainer.component.WebContainerImpl.start(WebContainerImpl.java:719)
        at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:1247)
        at com.ibm.ws.runtime.component.DeployedApplicationImpl.fireDeployedObjectStart(DeployedApplicationImpl.java:1514)
        at com.ibm.ws.runtime.component.DeployedModuleImpl.start(DeployedModuleImpl.java:704)
        at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:1096)
        at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:799)
        at com.ibm.ws.runtime.component.ApplicationMgrImpl$5.run(ApplicationMgrImpl.java:2315)
        at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:5488)
        at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:5614)
        at com.ibm.ws.security.core.SecurityContext.runAsSystem(SecurityContext.java:255)
        at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:2320)
        at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:436)
        at com.ibm.ws.runtime.component.CompositionUnitImpl.start(CompositionUnitImpl.java:123)
        at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:379)
        at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.access$500(CompositionUnitMgrImpl.java:127)
        at com.ibm.ws.runtime.component.CompositionUnitMgrImpl$CUInitializer.run(CompositionUnitMgrImpl.java:985)
        at com.ibm.wsspi.runtime.component.WsComponentImpl$_AsynchInitializer.run(WsComponentImpl.java:524)
        at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1909)
Caused by: java.lang.IllegalStateException: javassist.CannotCompileException: by java.lang.LinkageError: org.springframework.aop.framework.ProxyCreatorSupport
        at org.springframework.aop.framework.JavassistApplicationContext.<clinit>(JavassistApplicationContext.java:36)
        ... 34 more
Caused by: javassist.CannotCompileException: by java.lang.LinkageError: org.springframework.aop.framework.ProxyCreatorSupport
        at javassist.ClassPool.toClass(ClassPool.java:1170)
        at javassist.ClassPool.toClass(ClassPool.java:1113)
        at javassist.ClassPool.toClass(ClassPool.java:1071)
        at javassist.CtClass.toClass(CtClass.java:1275)
        at org.springframework.aop.framework.JavassistApplicationContext.<clinit>(JavassistApplicationContext.java:34)
        ... 34 more
Caused by: java.lang.LinkageError: org.springframework.aop.framework.ProxyCreatorSupport
        at java.lang.ClassLoader.defineClassImpl(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:357)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:293)
        at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
        at java.lang.reflect.Method.invoke(Method.java:508)
        at javassist.ClassPool.toClass2(ClassPool.java:1183)
        at javassist.ClassPool.toClass(ClassPool.java:1164)
        ... 38 more

当我尝试对 org.springframework.aop.framework.ProxyCreatorSupport 进行操作时,我在这个 java 文件上收到此错误

package org.spring.aop.framework;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.LoaderClassPath;
import org.springframework.web.context.support.XmlWebApplicationContext;

public class JavassistApplicationContext extends XmlWebApplicationContext {

    static {
        ClassPool classPool = ClassPool.getDefault();
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            classPool.appendClassPath(new LoaderClassPath(classLoader));

            CtClass cc = classPool.get("org.spring.aop.framework.ProxyCreatorSupport");
            CtConstructor c = cc.getConstructors()[0];
            c.insertAfter("$0.aopProxyFactory = new org.spring.aop.framework.JavassistAopProxyFactory();");
            cc.toClass();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}

上线cc.toClass(); ,我收到这个异常。我在 WebSphere 上尝试了不同的类加载器方法来解决此异常并得到相同的错误。

现在我明白了linkage problem is occur when tries to modify the class already loaded by referenced classloader .能够解决这个错误,我 should unload the class first from the reference classloader我认为这很难。

  1. 所以我认为解决这个问题的唯一方法是在类加载器之前由任何类加载器实现字节码操作。不是吗?
  2. 如何使用 java 代理将现有代码更改为字节码操作?有什么想法和建议吗?请不要提出重复的问题。这只是上一个问题的引用工作。

最佳答案

您需要写a Java agent并动态附加它以在加载时转换类。你可以找到一个很酷的教程here这解释了如何做到这一点。

请注意,此方法允许您在 JVM 加载类时拦截该类,并在实际加载完成后对其进行修改。

关于java - 如何使用 Javassist 进行字节码操作以解决链接错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46727348/

相关文章:

java - Spring 5 至少必须存在一个 JPA 元模型

java - spring batch 配置元素不可达

java - sql语句在集成测试结束前回滚

java - 删除Android中的所有sharedPreferences

java - Hibernate,不支持嵌套事务

java - 我编写的代码有问题吗?

hibernate 、检测和删除级联顺序

Android Studio 无法正确导入 androidx 测试类

java - XML 到 JSON 的转换会丢失一些 XML 标签

java - 属性文件中的 Spring 表单错误