6 Replies Latest reply on Aug 7, 2008 10:50 AM by dmlloyd

    Remoting unmarshalling vs. class loaders

    dmlloyd

       

      "scott.stark@jboss.org" wrote:
      I have been talking to Ron about some current remoting class loading issues that arise from the invocation handler being the only one who knows the correct class loader for unmarshalling application specific classes:

      1. thread pool receives a remoting request.
      2. unmarshall just enough to understand the request, but don't unmarshall any invocation payload. Application specific data needs to be isolated outside of the remoting control structures to allow this to happen.
      3. dispatch the request to a handler.
      4. handler sets the TCL
      5. handler or its delegate unmarshalls application payload
      6. application does what is does.
      7. handler serializes application return/exception and then unsets the TCL
      8. remoting layer completes request control information


      So the core of this issue is that Remoting 2 mixes control objects in with the invocation payload in the wire protocol. Or put more generally, a request may be comprised of objects that have to be unmarshalled by different classloaders, where the proper classloader may not be evident based on the current unmarshalling state. (Let me know if I'm not understanding something...)

      In R3 this is solved in part because there's no Remoting control data in the request itself. So as long as you keep your requests confined to a single classloader (on the receiving side) then things should work out. I think that associating a service with its appropriate classloader would be the right thing to do there (the protocol handler would then choose the classloader based on the service being invoked). Given the R3 design, which makes requests and client instances much more lightweight, mixing classloaders in requests would be an indication of improper service design - if you're doing that, you probably need multiple services (one for each aspect that lives in its own classloader).

      (Deliberately not yet broaching the topic of R3's remote classloading system)


        • 1. Re: Remoting unmarshalling vs. class loaders
          starksm64

           

          "david.lloyd@jboss.com" wrote:
          So as long as you keep your requests confined to a single classloader (on the receiving side) then things should work out. I think that associating a service with its appropriate classloader would be the right thing to do there (the protocol handler would then choose the classloader based on the service being invoked). Given the R3 design, which makes requests and client instances much more lightweight, mixing classloaders in requests would be an indication of improper service design - if you're doing that, you probably need multiple services (one for each aspect that lives in its own classloader).

          Agreed, the target of the remoting invocation should have a distinct class loader that would be set as the request TCL. However, if there is a lazy or streaming facility that allows the marshalling to occur at the remoting layer and there is object replacement via replaceObject, proxy replacement, etc., the marshaller needs the handler TCL saved for the duration of the response. Is there a way the handler can associate that with the response object?


          • 2. Re: Remoting unmarshalling vs. class loaders
            trustin

            Agreed. This issue can be fixed by redesigning the protocol. Mixing classloaders in a request object sounds strange to me, too.

            On the other hand, I'd like to know if there will be any potential issues with implementing R1/R2 transport for R3 regarding this issue. We still have to deal with mixed classloaders in the compatibility layer I guess?

            • 3. Re: Remoting unmarshalling vs. class loaders
              starksm64

              The remoting invocation handler is the only place where the correct class loader is known. The response object it returns is the only thing that can hold the class loader unless the handler itself is queried for this info. It could be hidden in an marshaller associated with the reply so its not an explicit part of the api, but having a marshaller being capable of knowing a handler specific class loader is what would be needed.

              • 4. Re: Remoting unmarshalling vs. class loaders
                dmlloyd

                 

                "scott.stark@jboss.org" wrote:
                "david.lloyd@jboss.com" wrote:
                So as long as you keep your requests confined to a single classloader (on the receiving side) then things should work out. I think that associating a service with its appropriate classloader would be the right thing to do there (the protocol handler would then choose the classloader based on the service being invoked). Given the R3 design, which makes requests and client instances much more lightweight, mixing classloaders in requests would be an indication of improper service design - if you're doing that, you probably need multiple services (one for each aspect that lives in its own classloader).

                Agreed, the target of the remoting invocation should have a distinct class loader that would be set as the request TCL. However, if there is a lazy or streaming facility that allows the marshalling to occur at the remoting layer and there is object replacement via replaceObject, proxy replacement, etc., the marshaller needs the handler TCL saved for the duration of the response. Is there a way the handler can associate that with the response object?


                You mean so that the client can pick the right classloader to unmarshal the response? I think that clients should also be associated with a CL as well (anyway we need to do that to allow us to specify a RemoteClassLoader on the client side). I doubt there is likely to be a 1:1 correspondence between classloaders on the client and server side, so I don't really see the benefit of annotating the response with classloader information.

                Setting the TCL for the duration of any task that handles a request is doable though. There are currently no plans to implement any form of lazy unmarshalling. We will need to ensure that the streaming facility can have access to the marshaller as well as the classloader.

                • 5. Re: Remoting unmarshalling vs. class loaders
                  starksm64

                   

                  "david.lloyd@jboss.com" wrote:

                  You mean so that the client can pick the right classloader to unmarshal the response? I think that clients should also be associated with a CL as well (anyway we need to do that to allow us to specify a RemoteClassLoader on the client side). I doubt there is likely to be a 1:1 correspondence between classloaders on the client and server side, so I don't really see the benefit of annotating the response with classloader information.

                  No, I mean if the response object container the unmarshalled object that is going to be streamed by the transport layer after the handler has cleared the TCL, possibly in another thread.

                  "david.lloyd@jboss.com" wrote:

                  Setting the TCL for the duration of any task that handles a request is doable though. There are currently no plans to implement any form of lazy unmarshalling. We will need to ensure that the streaming facility can have access to the marshaller as well as the classloader.

                  The TCL only works for class loading that occurs in the scope of a request dispatch. The concern is for marshalling that occurs after the handler has returned, and cleared the TCL.



                  • 6. Re: Remoting unmarshalling vs. class loaders
                    dmlloyd

                     

                    "scott.stark@jboss.org" wrote:
                    No, I mean if the response object container the unmarshalled object that is going to be streamed by the transport layer after the handler has cleared the TCL, possibly in another thread.


                    Ah, got it. In R3, the stream is associated with the request (and thereby the service), so on the server side, the proper TCL can easily be selected. Also, the server side contains a mechanism for dispatching asynchronous tasks (for the purpose of asynchronous cancellation originally) which can easily be leveraged for this purpose as well. The end result would be that any thread that does anything related to a request can be preconfigured ahead of time however we need.

                    On the client side it's a little different but I think that we could set it up to select the right classloader for the duration of any unmarshalling or stream handling operation regardless of thread through the way stream handler API is invoked. I'll double-check that to be sure though.