0

I have created a framework that uses LoadTimeWeaving. In some cases the classes that my framework are trying to weave have already been loaded. Thus these classes wont be handled by aspectj's LoadTimeWeaving.

My initial thought was to try and unload/reload the classes so that AspectJ could reload them during it's LoadTimeWeaving phase. But according to my findings that's impossible.

Some exampel code https://github.com/abrovinc/methodmock/blob/preloaded-class-test/example-projects/java-versions/java-1.6/src/test/java/com/example/ExampleTest.java

@Test
public void testExample() throws Exception {

    new Example();

    new LoadJavaAgent();

    mockMethod("methodToBeMocked").returns("Mock works");
    assertEquals("Mock works",Example.methodToBeMocked());
}

If Example is loaded before LoadJavaAgent is loaded the load time weaving that occurs once LoadJavaAgent is called wont affect Example class.

I would like an option to initiate a new object and have that object be handled by the LoadTimeWeaving

Regards

tkruse
  • 10,222
  • 7
  • 53
  • 80
Nosfert
  • 382
  • 1
  • 3
  • 11
  • 1
    Of course, AspectJ LTW is applied during class-loading. So if the class is loaded before the weaving agent, what do you expect? Why don't you load the agent via JVM command line parameter? Then it is there before your class is loaded. The only alternative is to create a new classloader hierarchy, load the weaver therein and then the target class afterwards. But then the weaver does not apply to the other classloader hierarchy in which the target class has already been loaded. Was that your question? Then I can convert this comment into an answer. Or what exactly is the question? – kriegaex Jan 14 '17 at 12:45
  • Yes that is a solution. But im not sure if people would want to do that extra step on their projects. – Nosfert Jan 16 '17 at 09:31
  • Im trying to create a mocking framework that uses aspects to intercept the methodcalls that should be mocked. I would want it to be a simple "plug n play" kind of feeling when you use it. Not having to define that the maven/gradle/ant parent pom should use a aspectj java agent would be nice. I have created a java class that loads the java agent on the fly but then I got this unexpected behaviour... So I think you are partially onto the answer im hopefully looking for. – Nosfert Jan 16 '17 at 09:44
  • 1
    I guess if you can really convince people of using yet another new-fangled mocking framework in addition to the excellent one contained in Spock or add-on stuff for JUnit like Mockito, EasyMock and PowerMock, then you can also convince them to use the framework as intended by you. You could also integrate the framework into the build process like the ones mentioned, provide a JUnit runner for it and what not. But we are slowly getting off topic here. – kriegaex Jan 17 '17 at 16:45
  • Yes. I just wanted you to have the background story. How would you crate a java loader that reloads the class and weave it? I have not had time to look into the sourcecode of aspectj but I suspect that aspectj has a classloader, and if so then i should be able to reuse that to reload the object. – Nosfert Jan 18 '17 at 07:48
  • 1
    I cloned your repo and saw that it works if either you do `new LoadJavaAgent();` before `new Example();` or you revert your test back to `ExampleTest extends LoadJavaAgent`. Can you help me understand why you do it wrong on purpose? Which situation are you trying to reproduce? – kriegaex Jan 18 '17 at 11:10
  • You cannot trick the JVM classloading hierarchy. Plus, AspectJ instrumentation does not support `redefineClasses()`. So either you load the agent via JVM command line or you switch to compile-time weaving in order to make sure that aspects are already woven when classes are loaded. You cannot eat the cake and keep it at the same time. – kriegaex Jan 18 '17 at 12:50
  • Yeah that was what i suspected. Thanks for the input. – Nosfert Jan 18 '17 at 12:57

0 Answers0