Giter Club home page Giter Club logo

Comments (20)

erkieh avatar erkieh commented on July 3, 2024

Sorry about that. I guess repackaging Cglib would be an option. This should sit in the core project, next to javassist? Would you like me to add it there?

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

I think it will not solve the issue - although the net.sf.cglib.proxy.Callback class will be available at startup, it will be different to the class loaded by webapp classloader.

If your code runs from "agent" classloader (directly from the plugin), it must be launched via java reflection, because "agent" classloader does not know anything about classes from weabpp.

The other way is to call the method from modified class in webapp classloader. It is possible, because all "agent" classes are replicated into all webapp classloaders (see org.hotswap.agent.util.classloader.ClassLoaderPatcher).

Javaassist is something else - it is included only to support bytecode manipulation.

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

I have removed the dependencies with the commit erkieh@e703606

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

There are still issues in multi classloader projects. The problem is with ProxyTransformationUtils.getClassPool() method. You need to have classPool with classpath of current classLoader - classPool.appendClassPath(new LoaderClassPath(classLoader)); - for each application classloader. You can add ClassPool method parameter to @OnClassLoadEvent annotated method and the framework will create correct ClassPool for you.

HOTSWAP AGENT: 7:35:58.319 ERROR (org.hotswap.agent.plugin.proxy.cglib.GeneratorParametersRecorder) - error modifying class for cglib proxy creation parameter recording
org.hotswap.agent.javassist.NotFoundException: org.springframework.cglib.core.ClassGenerator
    at org.hotswap.agent.javassist.ClassPool.get(ClassPool.java:445)
    at org.hotswap.agent.javassist.CtClassType.getInterfaces(CtClassType.java:685)
    at org.hotswap.agent.plugin.proxy.cglib.GeneratorParametersRecorder.transform(GeneratorParametersRecorder.java:33)
    at org.hotswap.agent.plugin.proxy.ProxyPlugin.transformDefinitions(ProxyPlugin.java:48)
    at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.hotswap.agent.annotation.handler.OnClassLoadedHandler.transform(OnClassLoadedHandler.java:157)

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

Thank you for the feedback. Up until now I have only used this plugin for development with an embedded Jetty server so the multi classloader environment issues had not come up.

I have done some refactoring and added more comments at https://github.com/HotswapProjects/HotswapAgent.git
Can you please take a look?

I have chosen to share the ClassPool instance between calls, because I Know that I need to access the classes from previous calls anyway.

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

Hi, I have run tests from HotswapAgentExamples project and it looks good.

There are still errors inside SpringPlugin (org.hotswap.agent.javassist.NotFoundException: net.sf.cglib.proxy.MethodInterceptor) because of EnhancerProxyCreater,getCp() method, which uses EnhancerProxyCreater.class.getClassLoader() classloader - this is still the HotswapAgent/root classloader, not the application classloader.

In some cases it would be convenient to use HotswapAgent concepts. For example ProxyPlugin:

  • ClassPool is available as method param
  • CtClass is available as method param, if modified, it is automatically converted to target bytecode
  • Concept of plugin "instance" - use @init to initialize classloader (see HotswapperPlugin). You can than use PluginManagerInvoker.callPluginMethod() to invoke plugin method, while application classloader (and ClassPool) will be instance fields.

It is not necessary to rewrite current code. However, using of common CtClass/ClassPool will enable the agent to share single instance across multiple plugins.

@init method will also clean the plugin instance after the associated webapp is undeployed. There is String initalizer = "{" + PluginManagerInvoker.buildInitializePlugin(ProxyPlugin.class) + "}"; code inside GeneratorParametersTransformer, but I am not sure what is the purpose, because the plugin instance is never used.

The code is quite complex and I have not yet time to go through it thoroughly, hence I may miss some important points.

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

I though the ClassLoaderPatcher defined all my plugin classes in the WebApp Classloader?

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

Indeed it did. But the EnhancerProxyCreater is now defined in both classloaders - main AND WebApp classloader.

How to use the class from WebApp classloader?

  • manually via reflection - WebAppClassloader.loadClass(EnhancerProxyCreater.getClass().getName())
  • use org.hotswap.agent.command.ReflectionCommand (see Hibernate plugin)
  • modify bytecode of a framework class running in WebApp classloader and call your class directly

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

Method number 3 should be in effect here.
I think the issue might have been with the ClassPool toClass method, which uses the ClassLoader of the ancestor thread by default. I have explicitly set it now and tried to make the Proxy plugin code simpler, while using more framework features.

I tried executing the run-tests.sh script in the examples project, but i receive the following error:

[WARNING] Error injecting: org.codehaus.cargo.maven2.ContainerStartMojo
com.google.inject.ProvisionException: Guice provision errors:

  1. Error injecting constructor, java.lang.NoClassDefFoundError: org/apache/tools
    /ant/BuildException

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

I think SpringPlugin.cglibAopProxyDisableCache should not be necessary when proxy replacement works.
But we should keep it around in case a user disables the Proxy plugin?
What do you think would be the best method to detect if Proxy plugin is enabled in the Spring plugin?

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

First, let me thank you for the plugin, it looks very promising. I have merged current version into master, but there are still several issues in my real-life projects. I will try to simulate it in https://github.com/HotswapProjects/HotswapAgentExamples/tree/master/spring-hibernate.

Proxy should be pretty core plugin and if the user disables it, I think it is Ok if Spring fails to reload proxied clasess. But you can use @Init PluginConfiguration config; config.isDisabledPlugin("pluginName");.

I now that run_test.sh is not optimal (plaform specific), but it just launches maven for several configurations. Can you run mvn clean install from command line and check, what the error is?

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

I found an issue in CtClassJavaProxyGenerator that i fixed in erkieh@34c4e0c

from hotswapagent.

edudant avatar edudant commented on July 3, 2024

All my issues were related to obsolete JavaBean cache. I have merged your latest version into master and added loader.loadClass("java.beans.Introspector").getMethod("flushCaches").invoke(null); to ProxyPlugin before any class modification. Now everything looks Ok, even complete recompilation of a project at runtime.

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

That is great to hear.

BTW Have you experienced any JVM locking/hanging while using this plugin? I have and I suspect it might have something to do with the SpringChangesAnalyzer I have added. Its hard to debug, because when it locks up, the only way I can get a stacktrace is with jstack using the -F option and even that does not show the java agent thread.

I have removed it's usage in my master branch erkieh@ac4395d.

from hotswapagent.

skybber avatar skybber commented on July 3, 2024

I don't use the Spring plugin but the last version hangs sometimes during boot up of my project (Tomcat / Seam + Hibernate + JSF).

from hotswapagent.

sribee avatar sribee commented on July 3, 2024

This issue is still seen with the latest code.

HOTSWAP AGENT: 1:32:48.345 ERROR (org.hotswap.agent.plugin.spring.getbean.EnhancerProxyCreater) - Creating a proxy failed
org.hotswap.agent.javassist.NotFoundException: net.sf.cglib.proxy.MethodInterceptor
    at org.hotswap.agent.javassist.ClassPool.get(ClassPool.java:445)
    at org.hotswap.agent.plugin.spring.getbean.EnhancerProxyCreater.buildProxyCallbackClass(EnhancerProxyCreater.java:221)
    at org.hotswap.agent.plugin.spring.getbean.EnhancerProxyCreater.getProxyCreationMethod(EnhancerProxyCreater.java:115)
    at org.hotswap.agent.plugin.spring.getbean.EnhancerProxyCreater.create(EnhancerProxyCreater.java:83)
    at org.hotswap.agent.plugin.spring.getbean.EnhancerProxyCreater.createProxy(EnhancerProxyCreater.java:78)
    at org.hotswap.agent.plugin.spring.getbean.ProxyReplacer.register(ProxyReplacer.java:46)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:968)

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

Please provide a quickstart demonstrating the problem. I have used it with some spring 3 and 4 versions and can't say i have seen this issue again.

from hotswapagent.

sribee avatar sribee commented on July 3, 2024

The problem is with Spring 4.1.5 release. It doesn't show up with spring 4.0.X versions.

But with Spring 4.0.X I see a different issue.

HOTSWAP AGENT: 10:59:23.399 ERROR (org.hotswap.agent.annotation.handler.OnClassLoadedHandler) - InvocationTargetException in transform method on plugin 'class org.hotswap.agent.plugin.proxy.ProxyPlugin' class 'com/Acme/service/AcmeServiceImpl$$EnhancerBySpringCGLIB$$b7103509'.
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.hotswap.agent.annotation.handler.OnClassLoadedHandler.transform(OnClassLoadedHandler.java:157)
    at org.hotswap.agent.annotation.handler.OnClassLoadedHandler$1.transform(OnClassLoadedHandler.java:76)
    at org.hotswap.agent.util.HotswapTransformer.transform(HotswapTransformer.java:129)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
    at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method)
    at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170)
    at org.hotswap.agent.config.PluginManager.hotswap(PluginManager.java:254)
    at org.hotswap.agent.plugin.hotswapper.HotswapperPlugin$1.executeCommand(HotswapperPlugin.java:94)
    at org.hotswap.agent.command.impl.CommandExecutor.run(CommandExecutor.java:25)
Caused by: java.lang.RuntimeException: java.lang.IllegalArgumentException: No such field class org.hotswap.agent.plugin.proxy.hscglib.GeneratorParams.getParam on org.hotswap.agent.plugin.proxy.hscglib.GeneratorParams@21079b1d
    at org.hotswap.agent.plugin.proxy.hscglib.GeneratorParametersTransformer.getGeneratorParams(GeneratorParametersTransformer.java:116)
    at org.hotswap.agent.plugin.proxy.ProxyPlugin.transformCglibProxy(ProxyPlugin.java:71)
    ... 14 more
Caused by: java.lang.IllegalArgumentException: No such field class org.hotswap.agent.plugin.proxy.hscglib.GeneratorParams.getParam on org.hotswap.agent.plugin.proxy.hscglib.GeneratorParams@21079b1d
    at org.hotswap.agent.util.ReflectionHelper.get(ReflectionHelper.java:84)
    at org.hotswap.agent.plugin.proxy.hscglib.GeneratorParams.valueOf(GeneratorParams.java:79)
    at org.hotswap.agent.plugin.proxy.hscglib.GeneratorParametersTransformer.getGeneratorParams(GeneratorParametersTransformer.java:114)
    ... 15 more
'''

from hotswapagent.

erkieh avatar erkieh commented on July 3, 2024

About the 4.0.x issue:
Are you sure you don't have any local changes?
For some reason ReflectionHelper is looking for a field named "getParam" but the String literal for the fieldname in
https://github.com/HotswapProjects/HotswapAgent/blob/4e1643652a9cb8719cd6a8cc6117a80b12eda092/plugin/hotswap-agent-proxy-plugin/src/main/java/org/hotswap/agent/plugin/proxy/hscglib/GeneratorParams.java
is "param"

from hotswapagent.

sribee avatar sribee commented on July 3, 2024

I didn't have any changes. But, I tried again after rebuilding, i don't see the issue any more. Thanks for checking on it, i will let you know if I see it again.

On a side note, I had to use a older revision ** Merge pull request #61 from frankdavid/master ** - commit sha1 - eff4f76 because the HEAD revision from git is failing during 'mvn clean install' with error

HOTSWAP AGENT: 9:56:53.480 ERROR (org.hotswap.agent.plugin.weld.command.BeanDeploymentArchiveAgent) - basePackage '/C:/workspace/git/HotswapAgent/plugin/hotswap-agent-weld-plugin/target/test-classes' not associated with any archiveAgent
Tests run: 7, Failures: 2, Errors: 1, Skipped: 0, Time elapsed: 3.384 sec <<< FAILURE! - in org.hotswap.agent.plugin.weld.WeldPluginTest
hotswapPrototypeTest(org.hotswap.agent.plugin.weld.WeldPluginTest)  Time elapsed: 1.232 sec  <<< FAILURE!
java.lang.AssertionError: null
    at org.junit.Assert.fail(Assert.java:86)
    at org.junit.Assert.assertTrue(Assert.java:41)
    at org.junit.Assert.assertTrue(Assert.java:52)
    at org.hotswap.agent.plugin.weld.WeldPluginTest.swapClasses(WeldPluginTest.java:166)
    at org.hotswap.agent.plugin.weld.WeldPluginTest.hotswapPrototypeTest(WeldPluginTest.java:125)

hotswapSeviceAddMethodTest(org.hotswap.agent.plugin.weld.WeldPluginTest)  Time elapsed: 1.102 sec  <<< FAILURE!
java.lang.AssertionError: null
    at org.junit.Assert.fail(Assert.java:86)
    at org.junit.Assert.assertTrue(Assert.java:41)
    at org.junit.Assert.assertTrue(Assert.java:52)
    at org.hotswap.agent.plugin.weld.WeldPluginTest.swapClasses(WeldPluginTest.java:166)
    at org.hotswap.agent.plugin.weld.WeldPluginTest.hotswapSeviceAddMethodTest(WeldPluginTest.java:77)

hotswapRepositoryNewMethodTest(org.hotswap.agent.plugin.weld.WeldPluginTest)  Time elapsed: 0.034 sec  <<< ERROR!
java.lang.NullPointerException: null
    at java.lang.String.length(String.java:623)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:414)
    at java.lang.StringBuilder.append(StringBuilder.java:132)
    at org.hotswap.agent.plugin.weld.testBeans.HelloServiceImpl.hello(HelloServiceImpl2.java:22)
    at org.hotswap.agent.plugin.weld.WeldPluginTest.hotswapRepositoryNewMethodTest(WeldPluginTest.java:108)


Results :

Failed tests: 
  WeldPluginTest.hotswapPrototypeTest:125->swapClasses:166 null
  WeldPluginTest.hotswapSeviceAddMethodTest:77->swapClasses:166 null

Tests in error: 
  WeldPluginTest.hotswapRepositoryNewMethodTest:108 ยป NullPointer

Tests run: 7, Failures: 2, Errors: 1, Skipped: 0

from hotswapagent.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.