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]
