From: Mike G. <mi...@el...> - 2007-01-15 22:41:22
|
> Have you tried printing out the identity of the various classloaders? Yup, it reports exactly what I'd expect. This is the output from the console: bootstrap.Main loader = sun.misc.Launcher$AppClassLoader@92e78c server.Main loader = java.net.FactoryURLClassLoader@19efb05 JettyEngine loader = java.net.FactoryURLClassLoader@c5495e The first is one of the first lines in the application: System.err.println("bootstrap.Main loader = " + com.xxxx.bootstrap.Main.class.getClassLoader().toString()); The second is in the constructor of the Main class that actually starts the app server. This class is constructed immediately via the bootstrap loader: System.err.println("server.Main loader = " + com.xxxx.Main.class.getClassLoader().toString()); The third is inside the first class created by the loader that we use for Jetty: System.err.println("JettyEngine loader = " + com.xxxx.servers.webserver.jetty.JettyEngine.class.getClassLoader().toString()); We are using URLClassLoader for all of our class loaders. Each classloader is created with an array of Jars and an explicit reference to the parent loader. The specific syntax is something like this: ClassLoader classLoader = URLClassLoader.newInstance(urls, WebServerWrapper.class.getClassLoader()); I've printed out the contents of "urls" before and can confirm that it doesn't contain any surprises at all. The "JettyEngine loader" contains all the Jetty and Servlet API jars as well as a jar that contains the "JettyEngine" itself. We are using Michael Grundvig Electrotank, Inc http://www.electrotank.com ----- Original Message ----- From: "Jan Bartel" <ja...@mo...> To: "Jetty usage, help & informal support " <jet...@li...> Sent: Monday, January 15, 2007 3:58 PM Subject: Re: [Jetty-support] Embedded Jetty Classloader Issues > Hi Mike, > > Have you tried printing out the identity of the various classloaders? > > cheers > Jan > > Mike Grundvig wrote: >> I guess what I don't understand is this part right here: >> >> WebAppClassLoader.class.getClassLoader()!=null?WebAppClassLoader.class.getClassLoader() >> >> That SHOULD be working already. I can add this line of code right before >> I >> instantiate the Jetty server instance: >> >> Thread.currentThread().setContextClassLoader(WebAppClassLoader.class.getClassLoader()); >> >> and everything works great but if I don't explicitly set the context >> classloader it fails. What makes this interesting is that that line is >> added >> to JettyEngine which is in a jar that gets loaded by the same classloader >> that loads all the Jetty (and servlet-api) jars so I KNOW all the needed >> jars are there. >> >> Sorry if I sound dense here, but something just isn't working right and >> I'm >> starting to wonder if it's my code or some other problem... >> >> Michael >> >> ----- Original Message ----- >> From: "Jan Bartel" <ja...@mo...> >> To: "Jetty usage, help & informal support " >> <jet...@li...> >> Sent: Monday, January 15, 2007 3:22 PM >> Subject: Re: [Jetty-support] Embedded Jetty Classloader Issues >> >> >>> Mike, >>> >>> welcome to the wonderful world of complex j2ee classloading hierarchies! >>> >>> Each webapp (in jetty) has a classloader, which wants as it's parent the >>> classloader that loaded the jetty classes. In the straightforward case >>> where all of the jars are on the system classpath of the embedded code, >>> then this is trivial. If, however, you are doing something more complex, >>> then you need to be able to communicate which classloader is the one >>> that loaded the jetty code, so that the webapp can work out who it's >>> parent is. >>> >>> The relevant code is in org.mortbay.jetty.webapp.WebAppClassLoader: >>> >>> public WebAppClassLoader(ClassLoader parent, WebAppContext context) >>> throws IOException >>> { >>> super(new URL[]{},parent!=null?parent >>> >>> :(Thread.currentThread().getContextClassLoader()!=null?Thread.currentThread().getContextClassLoader() >>> >>> :(WebAppClassLoader.class.getClassLoader()!=null?WebAppClassLoader.class.getClassLoader() >>> :ClassLoader.getSystemClassLoader()))); >>> .... >>> } >>> >>> >>> As you can see, it goes to some trouble to try to automatically >>> work out who the parent classloader is. Setting the thread context >>> classloader >>> will definitely allow it to work out who the parent is. >>> >>> regards >>> Jan >>> >>> Mike Grundvig wrote: >>>> If only I'd poked around rather then send that last message. Sorry. >>>> It's >>>> working now. Just took this line right above the Jetty creation code: >>>> >>>> Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); >>>> >>>> I assume I can set the classloader back as soon as that code is >>>> complete >>>> without causing any problems in Jetty? The whole reason for this design >>>> was >>>> to avoid "polluting" my main server hierarchy with Jetty-specific jars. >>>> Something like this... >>>> >>>> Classloader currentContextLoader = >>>> Thread.currentThread().getContextClassLoader(); >>>> Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader()); >>>> // load jetty >>>> Thread.currentThread().setContextClassLoader(currentContextLoader ); >>>> >>>> Also, why doesn't jetty does this for me automatically? I don't >>>> understand >>>> why Jetty makes me explicitly tell it what loader to use. Seems like it >>>> could just take care of this. Thanks! >>>> >>>> Michael >>>> >>>> >>>> ----- Original Message ----- >>>> From: "Mike Grundvig" <mi...@el...> >>>> To: "Jetty usage, help & informal support " >>>> <jet...@li...> >>>> Sent: Monday, January 15, 2007 9:27 AM >>>> Subject: Re: [Jetty-support] Embedded Jetty Classloader Issues >>>> >>>> >>>>> Hmmm, intersecting. That most certainly could be the case but I don't >>>>> really >>>>> know why. I don't set the context classloader ever. I create Jetty >>>>> like >>>>> this >>>>> (formatting/spaces removed for brevity): >>>>> >>>>> ListenerConfiguration listenerConfiguration = config.getWebListener(); >>>>> server = new Server(); >>>>> Connector connector=new SelectChannelConnector(); >>>>> connector.setHost(listenerConfiguration.getHost()); >>>>> connector.setPort(listenerConfiguration.getPort()); >>>>> server.setConnectors(new Connector[]{connector}); >>>>> JettyRequestHandler handler = new >>>>> JettyRequestHandler(serverReference); >>>>> server.addHandler(handler); >>>>> WebAppDeployer deployer = new WebAppDeployer(); >>>>> deployer.setWebAppDir(Constants.WEB_APP_DIRECTORY); >>>>> deployer.setContexts(server); >>>>> deployer.setExtract(true); // extract war files to a temporary >>>>> directory >>>>> deployer.setAllowDuplicates(false); // allow duplicate contexts >>>>> server.addLifeCycle(deployer); >>>>> >>>>> The only interesting lines are the JettyRequestHandler ones. This is a >>>>> custom request handler needed so we can pass a reference to the >>>>> application >>>>> itself and make it's API available to the applications. >>>>> >>>>> This code is all within JettyEngine (from the stack trace in a >>>>> previous >>>>> message below). And in your example, would be the [Jetty] classloader. >>>>> I'm >>>>> not ever setting the context classloader directly. All of my >>>>> classloaders >>>>> are used/created like this: >>>>> >>>>> ClassLoader classLoader = URLClassLoader.newInstance(urls, >>>>> WebServerWrapper.class.getClassLoader()); >>>>> Class<? extends WebServer> mainClass = null; >>>>> Class<?> initialMainClass = >>>>> classLoader.loadClass("com.xxxx.servers.webserver.jetty.JettyEngine"); >>>>> mainClass = initialMainClass.asSubclass(WebServer.class); >>>>> >>>>> This code you see here runs inside of the WebServerWrapper (from the >>>>> trace >>>>> below) and is in the [Server] loader as per your example. This shows >>>>> you >>>>> were I created the [Jetty] loader and started using it. WebServer is >>>>> simply >>>>> an interface that exists in the [Server] loader and provides some >>>>> basic >>>>> methods like init, start, stop, etc. The "urls" I pass into the >>>>> [Jetty] >>>>> loader are all the Jetty dependencies + JettyEngine and >>>>> JettyRequestHandler >>>>> (which are stored in a separate jar and NOT contained in the [Server] >>>>> loader >>>>> path. >>>>> >>>>> I'm using classloaders all through the server and have several other >>>>> hierarchies. Jetty is the only one that didn't work right out of the >>>>> gate >>>>> and I'm a bit confused. It's like it's trying to do something tricky >>>>> with >>>>> it's core loader rather then just letting the hierarchy work as >>>>> designed. >>>>> I'm open to any suggestions on how to correct this and am stumped >>>>> currently. >>>>> This is my first real work with classloaders so I'm sure it's my >>>>> mistake >>>>> somewhere but I'm not seeing it. Thanks! >>>>> >>>>> Michael Grundvig >>>>> Electrotank, Inc >>>>> http://www.electrotank.com >>>>> >>>>> >>>>> ----- Original Message ----- >>>>> From: "Tim Vernum" <ti...@ad...> >>>>> To: "Jetty usage, help & informal support " >>>>> <jet...@li...> >>>>> Sent: Monday, January 15, 2007 6:09 AM >>>>> Subject: Re: [Jetty-support] Embedded Jetty Classloader Issues >>>>> >>>>> >>>>>> On 15/01/2007, at 1:31 AM, Mike Grundvig wrote: >>>>>> >>>>>>> Hi Jan, this is the stack trace below. There are several other log >>>>>>> entries, >>>>>>> but they all look to be the same. I've replaced a couple package >>>>>>> names for >>>>>>> pseudo-security (it will keep the client happy I suppose): >>>>>> The good old guys at xxxx.com - I know them well :) >>>>>> >>>>>>> For reference, the bootstap.Main class is in the VM classloader via >>>>>>> the -jar >>>>>>> command. RegistryServer is in the classloader created by the >>>>>>> bootstrap.Main >>>>>>> class. JettyEngine is in the final classloader created by the >>>>>>> WebServerWrapper class. >>>>>> I'm going to call the classloaders [Boot], [Server], [Jetty], >>>>>> [WebApp]. >>>>>> I hope they make sense :) >>>>>> >>>>>> I agree with your assessment that the causes is probably classloader >>>>>> issues. >>>>>> It looks like the parent of [WebApp] is either [Server] or [Boot], >>>>>> but it needs to be [Jetty]. >>>>>> >>>>>> The piece of code that does that is: >>>>>> >>>>>> :(Thread.currentThread().getContextClassLoader()! >>>>>> =null?Thread.currentThread().getContextClassLoader() >>>>>> :(WebAppClassLoader.class.getClassLoader()! >>>>>> =null?WebAppClassLoader.class.getClassLoader() >>>>>> >>>>>> :ClassLoader.getSystemClassLoader()))); >>>>>> >>>>>> (about line 70, or r1476 or WebAppClassLoader.java) >>>>>> >>>>>> The only conceivable way I can see that [WebApp] would be getting the >>>>>> wrong classloader for its parent would be >>>>>> if the context class loader was set at the time that [WebApp] was >>>>>> created (which will be on deployment). >>>>>> >>>>>> Can you check whether you're setting the context classloader to >>>>>> [Server] at some point? >>>>>> If so, you'll probably need to point it to [Jetty] while you run the >>>>>> deployer. >>>>>> >>>>>> ------------------------------------------------------------------------- >>>>>> Take Surveys. Earn Cash. Influence the Future of IT >>>>>> Join SourceForge.net's Techsay panel and you'll get the chance to >>>>>> share >>>>>> your >>>>>> opinions on IT & business topics through brief surveys - and earn >>>>>> cash >>>>>> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >>>>>> _______________________________________________ >>>>>> Jetty-support mailing list >>>>>> Jet...@li... >>>>>> https://lists.sourceforge.net/lists/listinfo/jetty-support >>>>>> >>>>> >>>>> ------------------------------------------------------------------------- >>>>> Take Surveys. Earn Cash. Influence the Future of IT >>>>> Join SourceForge.net's Techsay panel and you'll get the chance to >>>>> share >>>>> your >>>>> opinions on IT & business topics through brief surveys - and earn cash >>>>> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >>>>> _______________________________________________ >>>>> Jetty-support mailing list >>>>> Jet...@li... >>>>> https://lists.sourceforge.net/lists/listinfo/jetty-support >>>>> >>>> >>>> >>>> ------------------------------------------------------------------------- >>>> Take Surveys. Earn Cash. Influence the Future of IT >>>> Join SourceForge.net's Techsay panel and you'll get the chance to share >>>> your >>>> opinions on IT & business topics through brief surveys - and earn cash >>>> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >>>> _______________________________________________ >>>> Jetty-support mailing list >>>> Jet...@li... >>>> https://lists.sourceforge.net/lists/listinfo/jetty-support >>>> >>> >>> ------------------------------------------------------------------------- >>> Take Surveys. Earn Cash. Influence the Future of IT >>> Join SourceForge.net's Techsay panel and you'll get the chance to share >>> your >>> opinions on IT & business topics through brief surveys - and earn cash >>> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >>> _______________________________________________ >>> Jetty-support mailing list >>> Jet...@li... >>> https://lists.sourceforge.net/lists/listinfo/jetty-support >>> >> >> >> >> ------------------------------------------------------------------------- >> Take Surveys. Earn Cash. Influence the Future of IT >> Join SourceForge.net's Techsay panel and you'll get the chance to share >> your >> opinions on IT & business topics through brief surveys - and earn cash >> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV >> _______________________________________________ >> Jetty-support mailing list >> Jet...@li... >> https://lists.sourceforge.net/lists/listinfo/jetty-support >> > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share > your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > Jetty-support mailing list > Jet...@li... > https://lists.sourceforge.net/lists/listinfo/jetty-support > |