The typical use of remoting involves synchronous request-response on some remote service. So you typically create an interface for the service (or use some class if you prefer) and then create a client side proxy which takes care of the messaging.
The Spring remoting framework takes care of the creation of the proxy (which uses Spring AOP, using either dynamic proxies or CGLIB). Then all invocations on the proxy result in remote messages being sent to some service.
A service exporter then consumes the message on the server side and sends a response back to the client.
When using the JMS binding, the client side uses a temporary queue for its inbound traffic. Remote requests can be sent on a queue or topic. For notifications you may wish to use a topic, so that many processes can subscribe to the notification; for operations (like placing on order) you typically would use a queue so that a single service can consume the message.
Under the hood the out of the box Lingo provider uses a single JMS Requestor to handle the client side which uses a pooled JMS connection, session, producer, consumer and uses correlationIDs on the messages to route inbound responses and notifications to request-results or to fire client side listeners.
One way invocations
The Metadata Strategy is used to decide which methods can be defined as asynchronous one-way invocations. Typically only methods which have a void result and throw no checked exceptions can be used as a one-way call. If enabled, all void non-exception method invocations can be used as one-ways.
Alternatively you can use JSR 181 annotations in Java 5 to mark methods as being one way.
Remote objects and async request-response
When invoking a method on the client side you can pass remote objects as parameters into method calls. The Metadata Strategy is used to decide which objects are remote. Remote objects are never passed by value in the message and instead a remote reference (correlation ID) is sent instead.
In JMS terms, we send a correlation ID per each remote object which is then used on the client side.
On the server side we take the remote reference in the message and turn it into a proxy so that the server-side service can call back the client using regular POJO classes/interfaces.
In terms of lifecycle, the client side Java code is in complete control of the lifecycle of the remote objects; they are kept around as long as the application logic requires (so you can use remote objects for one-shot message exchanges or long running exchanges).
Lingo uses a weak reference to the client side remote object; so that whenever the client discards the object it will get garbage collected.
On the server side we have a similar structure (which acts as a cache, so that if many requests come in with the same remote object reference, we'll reuse the same proxy). Again the business logic on the server side is the deciding factor in how long the proxy is kept around for.
So there is no explicit distributed garbage collection required.
Note that Lingo assumes a pure SOA architecture, where each service is stateless - or that all state is stored in a shared store so that there is no requirement for stateful session beans. If required a binding could be used to provide the behaviour of statefull session beans, via using some kind of exclusive queue with JMS so that a single consumer is processing all requests on a given queue to ensure statefulness.
Each binding is responsible for marshalling; usually this should be pluggable so that you can decide exactly how to marshall requests and responses onto the wire.
In the JMS provider, we default to using ObjectMessage and serialization of the LingoInvocation instances. You can plug in other options, such as an XStream marshaller to use XML as the payload.