FI

---------- Forwarded message ----------
From: Joseph Pachod <[email protected]>
Date: 2012/6/25
Subject: Re: WOInject: harmed twice by classloader manipulation
To: Henrique Prange <[email protected]>


HI Henrique

I finally had the  time to test your changes, launching my app from
another class than the application one.

It works smoothly, so well done, thanks :)

Only issue left is how to tackle the integration of this fix. Indeed
we have something like 300 launchers currently, all being in their
application's class. I've to figure out a way to cleanly migrate them
all. Or maybe you've a better way, if so let me know.

Thanks again !

As a side note: how are you able to figure out which class get loaded
when precisely? I

Best
Joseph

2012/6/18 Henrique Prange <[email protected]>:
> Hi Joseph,
>
> This error occurs if you run the application through the Application's main 
> method. The static initialization of the ERXApplication class triggers the 
> load of the _NSUtilities class. You need to run the application from a 
> separated class, like the AppRunner I've described, to ensure the 
> _NSUtilities has not been loaded yet.
>
> Sorry for this inconvenience, but it's the only way I've found to make it 
> work without a special classloader.
>
> Cheers,
>
> Henrique
>
> On 13/06/2012, at 19:53, Joseph Pachod wrote:
>
>> Hi Henrique
>>
>> Thanks for the feedbacks.
>>
>> I've been short on time recently, so I quickly tried your fix but I
>> encounter the following issue:
>> java.lang.reflect.InvocationTargetException
>>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>       at 
>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>       at 
>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>       at java.lang.reflect.Method.invoke(Method.java:597)
>>       at com.resurgences.guice.WOInject.loadClass(WOInject.java:158)
>>       at com.resurgences.guice.WOInject.main(WOInject.java:117)
>>       at 
>> com.resurgences.demo.admin.ApplicationAdminDemo.main(ApplicationAdminDemo.java:14)
>> Caused by: java.lang.LinkageError: loader (instance of
>> sun/misc/Launcher$AppClassLoader): attempted  duplicate class
>> definition for name: "com/webobjects/foundation/_NSUtilities"
>>       at java.lang.ClassLoader.defineClass1(Native Method)
>>       at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
>>       at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
>>       at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
>>       ... 7 more
>>
>> As I should be sleeping, I don't have much time to investigate right
>> now, but I'll soon. Line numbers doesn't match your code since there
>> are the extra guice stuff in there as well. Furthermore, I effectively
>> have two instances of this class on my classpath (ERExtensions and
>> JavaFoundations classes), so it doesn't look incorrect.
>>
>> BTW, are you sure Guice AOP works for binding realized through a
>> provider? I have the memory it doesn't... If not, just injecting
>> members after objects creation through _NSUtilities looks like good
>> enough.
>>
>> Thanks again for your helpful answers :)
>>
>> best
>> joseph
>>
>> 2012/6/10 Henrique Prange <[email protected]>:
>>> Joseph,
>>>
>>> I have created a issue [1] to track this problem.
>>>
>>> There is a new commit in the hotfix-classloading branch that tries to solve 
>>> the problem. It removes the dependency on a custom class loader. It's still 
>>> very experimental, but I would like to know if this patch solves your 
>>> problem.
>>>
>>> There is one requirement: you have to create a AppRunner class, and start 
>>> your application from it. Here is an example of a very simple runner:
>>>
>>> public class AppRunner {
>>>    public static void main(String[] args) {
>>>        WOInject.init("your.app.Application", args);
>>>    }
>>> }
>>>
>>> I've deployed a new WOInject SNAPSHOT to the WOCommunity repository. Just 
>>> update to the 1.1-SNAPSHOT version in your pom to download the latest 
>>> changes.
>>>
>>> [1]https://github.com/hprange/woinject/issues/7
>>>
>>> Cheers,
>>>
>>> Henrique
>>>
>>> On 07/06/2012, at 23:30, Henrique Prange wrote:
>>>
>>>> Hi Joseph,
>>>>
>>>> On 06/06/2012, at 04:04, Joseph Pachod wrote:
>>>>
>>>>> Hi all
>>>>>
>>>>> We've been using WOInject for a few months and encountered two issues
>>>>> due to the classloader manipulation done at startup (the one to enable
>>>>> interception through javassist, in the WOInject class).
>>>>>
>>>>
>>>> You're not alone. I've faced problems because of the classloader 
>>>> manipulation too. Take a look at issue #2 [1]. I've provided a simple fix, 
>>>> but I know it is not a definitive solution.
>>>>
>>>>> The first issue is a known Guice 2.0 bug
>>>>> (http://code.google.com/p/google-guice/issues/detail?id=343). This one
>>>>> pops up when from Guice grabs some class from another classloader that
>>>>> the one it was started in. In our case, it meant Guice was grabing
>>>>> some class from the default class loader instead of the the javassist
>>>>> one. It appeared in a very unexpected way: suddenly one binding was
>>>>> causing the whole application to break down. Finally, we had to switch
>>>>> to Guice 3.0, which incorporates the bug fix and avoids the issue to
>>>>> show up another time somewhere else. Turned out since  that the
>>>>> woinject repo on github states "Guice 3.0" as a requirement. Was this
>>>>> bug the reason for it?
>>>>>
>>>>
>>>> In fact, I was not aware of this Guice bug until now. :)
>>>>
>>>> The WOInject code responsible for object instantiation was heavily 
>>>> inspired by the AssistedInject module. It requires the 
>>>> bind().toConstructor() method API added in Guice 3.0. To support Guice 
>>>> 2.0, WOInject would not be able to take advantage of the AOP support, for 
>>>> instance.
>>>>
>>>>> The second issue is a security exception when trying to encrypt some
>>>>> file. The issue was boiled down to a classloader one again, the
>>>>> required class being "on the bootclasspath" instead of the current
>>>>> classloader (the javassist one). I append the stack trace to the end
>>>>> of this mail, if some one wants to have a look at it.
>>>>>
>>>>
>>>> This problem seems to be related to the issue #2 mentioned above. Clearly, 
>>>> an alternative is required to the Javassist classloader to solve this 
>>>> problem.
>>>>
>>>>> In order to get rid of this bug, we ended removing the classloading
>>>>> trick and, instead, using our own _NSUtilities where we do the
>>>>> injector.injectMembers(newInstance) ourselves. In order to make it
>>>>> possible, we made sure our own version of this class came on top of
>>>>> the classpath provided to the application (thanks to Maven). Since it
>>>>> works again.
>>>>>
>>>>> What do you think of that ? Could it be done as well in WOInject ?
>>>>>
>>>>
>>>> Yes. It could be done. However, this solution also has some problems:
>>>>
>>>> 1) It doesn't scale: that is the same approach employed by Wonder. We 
>>>> can't apply this kind of solution every time, for every framework.
>>>>
>>>> 2) It is subject to license issues.
>>>>
>>>> 3) It makes the user responsible for the solution of the problem. This 
>>>> problem is an extension of the first problem. In the beginning, 
>>>> ERExtensions should come first in the classpath. Then ERFoundation and 
>>>> ERWebObjects were created and took precedence. With this solution, 
>>>> WOInject must come before those libraries.
>>>>
>>>> 4) I'm not sure this solution works in a JEE environment.
>>>>
>>>> Changing the behavior of core classes of WebObjects is a general problem 
>>>> that anyone developing WO apps/frameworks face sooner or later. IMHO, we 
>>>> should develop a common solution in Wonder, some kind of ERPatcher 
>>>> framework. This would enable us to solve long-standing problems without 
>>>> violating the Apple license and in an organized manner. I really would 
>>>> like to know what others think about it. I'm really inclined to implement 
>>>> this framework, as soon as I figure out how. :)
>>>>
>>>>> Indeed, we were planning to use WOInject once the "WOInjectProposal"
>>>>> on github would have been incorporated.
>>>>>
>>>>
>>>> I'm planning to add this feature in the next release. I'm really out of 
>>>> time right now, but it is in my TODO list.
>>>>
>>>>> Personally, getting rid of classloader manipulations would be a plus
>>>>> IMHO. It removes a whole bunch of potential issues, from memory leaks
>>>>> to "classes from the wrong classloader".
>>>>>
>>>>
>>>> Classloader manipulations are complicated and can have side effects. 
>>>> However, it has been widely used in Java frameworks (including Guice). 
>>>> I'll try to produce a better solution. I'll ping you as soon as I have a 
>>>> new version for testing.
>>>>
>>>>> For sure, I may miss some good points of javassist, so I'm really
>>>>> eager to read you back. Alternative solutions are also welcome, but
>>>>> the few I could make up (using an agent instead of classloader
>>>>> manipulation for example) don't come for cheap neither: overall class
>>>>> shadowing and classpath ordering look like the less impacting option.
>>>>>
>>>>
>>>> I also would like to avoid using an agent to solve this problem. IMHO, we 
>>>> have the following alternatives:
>>>>
>>>> 1) A better custom classloader: the Javassist classloader is just an 
>>>> example of how to create a Classloader able to load Javassist manipulated 
>>>> classes. We can write a better one that loads only the _NSUtilities class 
>>>> from Javassist and delegates everything else to the parent classloader.
>>>>
>>>> 2) Loading the manipulated classes right on the System classloader: the 
>>>> manipulated _NSUtilities could be loaded directly in the System 
>>>> classloader through reflection. I don't know what are the side effects of 
>>>> this solution yet.
>>>>
>>>> 3) Classpath ordering: as you mentioned, avoids runtime problems at the 
>>>> cost of delegating the responsibility to the user of the library.
>>>>
>>>> I'll try to implement the first solution and send you a new version of 
>>>> WOInject as soon as possible.
>>>>
>>>> [1]https://github.com/hprange/woinject/issues/2
>>>>
>>>> Cheers,
>>>>
>>>> Henrique
>>>
>

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to