public class Channel extends java.lang.Object implements VirtualChannel, java.io.Closeable
A Channel
is a mechanism for two JVMs to communicate over
bi-directional InputStream
/OutputStream
pair.
Channel
represents an endpoint of the stream, and thus
two Channel
s are always used in a pair.
Communication is established as soon as two Channel
instances
are created at the end fo the stream pair
until the stream is terminated via close()
.
The basic unit of remoting is an executable Callable
object.
An application can create a Callable
object, and execute it remotely
by using the call(Callable)
method or callAsync(Callable)
method.
In this sense, Channel
is a mechanism to delegate/offload computation
to other JVMs and somewhat like an agent system. This is bit different from
remoting technologies like CORBA or web services, where the server exposes a
certain functionality that clients invoke.
Callable
object, as well as the return value / exceptions,
are transported by using Java serialization. All the necessary class files
are also shipped over Channel
on-demand, so there's no need to
pre-deploy such classes on both JVMs.
Channel
builds its features in a layered model. Its higher-layer
features are built on top of its lower-layer features, and they
are called layer-0, layer-1, etc.
Command
for more details. This is for higher-level features,
and not likely useful for applications directly.
Request
for more details. This is for higher-level features,
and not likely useful for applications directly.
Modifier and Type | Class and Description |
---|---|
static class |
Channel.Listener
Callback "interface" for changes in the state of
Channel . |
static class |
Channel.Mode
Communication mode used in conjunction with
ClassicCommandTransport . |
Modifier and Type | Field and Description |
---|---|
java.util.concurrent.atomic.AtomicInteger |
classLoadingCount
Total counts of remote classloading activities.
|
java.util.concurrent.atomic.AtomicLong |
classLoadingTime
Total number of nanoseconds spent for remote class loading.
|
static int |
PIPE_WINDOW_SIZE |
Capability |
remoteCapability
Capability of the remote
Channel . |
java.util.concurrent.atomic.AtomicInteger |
resourceLoadingCount
Total count of remote resource loading.
|
java.util.concurrent.atomic.AtomicLong |
resourceLoadingTime
Total number of nanoseconds spent for remote resource loading.
|
Constructor and Description |
---|
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
Channel.Mode mode,
java.io.InputStream is,
java.io.OutputStream os) |
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
Channel.Mode mode,
java.io.InputStream is,
java.io.OutputStream os,
java.io.OutputStream header) |
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
Channel.Mode mode,
java.io.InputStream is,
java.io.OutputStream os,
java.io.OutputStream header,
boolean restricted) |
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
Channel.Mode mode,
java.io.InputStream is,
java.io.OutputStream os,
java.io.OutputStream header,
boolean restricted,
java.lang.ClassLoader base)
Creates a new channel.
|
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
CommandTransport transport,
boolean restricted,
java.lang.ClassLoader base)
Creates a new channel.
|
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
java.io.InputStream is,
java.io.OutputStream os) |
Channel(java.lang.String name,
java.util.concurrent.ExecutorService exec,
java.io.InputStream is,
java.io.OutputStream os,
java.io.OutputStream header) |
Modifier and Type | Method and Description |
---|---|
void |
addListener(Channel.Listener l)
Registers a new
Channel.Listener . |
void |
addLocalExecutionInterceptor(CallableFilter filter)
Adds a
CallableFilter that gets a chance to decorate every Callable s that run locally
sent by the other peer. |
<V,T extends java.lang.Throwable> |
call(Callable<V,T> callable)
Makes a remote procedure call.
|
<V,T extends java.lang.Throwable> |
callAsync(Callable<V,T> callable)
Makes an asynchronous remote procedure call.
|
void |
close()
Performs an orderly shut down of this channel (and the remote peer.)
|
void |
close(java.lang.Throwable diagnosis)
Closes the channel.
|
ListeningPort |
createLocalToRemotePortForwarding(int recvPort,
java.lang.String forwardHost,
int forwardPort)
Starts a local to remote port forwarding (the equivalent of "ssh -L").
|
ListeningPort |
createRemoteToLocalPortForwarding(int recvPort,
java.lang.String forwardHost,
int forwardPort)
Starts a remote to local port forwarding (the equivalent of "ssh -R").
|
static Channel |
current()
This method can be invoked during the serialization/deserialization of
objects when they are transferred to the remote
Channel ,
as well as during Callable.call() is invoked. |
void |
dumpExportTable(java.io.PrintWriter w)
Dumps the list of exported objects and their allocation traces to the given output.
|
<T> T |
export(java.lang.Class<T> type,
T instance)
Exports an object for remoting to the other
Channel
by creating a remotable proxy. |
long |
getLastHeard() |
java.lang.String |
getName() |
<T> T |
getProperty(ChannelProperty<T> key) |
java.lang.Object |
getProperty(java.lang.Object key)
Gets the application specific property set by
setProperty(Object, Object) . |
<T> T |
getRemoteProperty(ChannelProperty<T> key) |
java.lang.Object |
getRemoteProperty(java.lang.Object key)
Gets the property set on the remote peer.
|
java.io.OutputStream |
getUnderlyingOutput()
Deprecated.
Future version of the remoting module may add other modes of creating channel
that doesn't involve stream pair. Therefore, we aren't committing to this method.
This method isn't a part of the committed API of the channel class.
|
boolean |
isRestricted()
Returns true if this channel is currently does not load classes from the remote peer.
|
void |
join()
Waits for this
Channel to be closed down. |
void |
join(long timeout)
Waits for this
Channel to be closed down, but only up the given milliseconds. |
void |
pin(java.lang.Object instance)
Increase reference count so much to effectively prevent de-allocation.
|
void |
pinClassLoader(java.lang.ClassLoader cl)
Pin down the exported classloader.
|
boolean |
preloadJar(Callable<?,?> classLoaderRef,
java.lang.Class... classesInJar)
Preloads jar files on the remote side.
|
boolean |
preloadJar(java.lang.ClassLoader local,
java.lang.Class... classesInJar) |
boolean |
preloadJar(java.lang.ClassLoader local,
java.net.URL... jars) |
boolean |
removeListener(Channel.Listener l)
Removes a listener.
|
void |
removeLocalExecutionInterceptor(CallableFilter filter)
Rmoves the filter introduced by
addLocalExecutionInterceptor(CallableFilter) . |
void |
resetPerformanceCounters()
Resets all the performance counters.
|
<T> T |
setProperty(ChannelProperty<T> key,
T value) |
java.lang.Object |
setProperty(java.lang.Object key,
java.lang.Object value)
Sets the property value on this side of the channel.
|
void |
setRestricted(boolean b) |
hudson.remoting.ExportTable.ExportList |
startExportRecording() |
void |
syncIO()
Blocks until all the I/O packets sent before this gets fully executed by the remote side, then return.
|
void |
syncLocalIO()
Blocks until all the I/O packets sent from remote is fully locally executed, then return.
|
protected void |
terminate(java.io.IOException e)
Aborts the connection in response to an error.
|
java.lang.String |
toString() |
<T> T |
waitForProperty(ChannelProperty<T> key) |
java.lang.Object |
waitForProperty(java.lang.Object key)
Works like
getProperty(Object) but wait until some value is set by someone. |
<T> T |
waitForRemoteProperty(ChannelProperty<T> key) |
java.lang.Object |
waitForRemoteProperty(java.lang.Object key)
Gets the property set on the remote peer.
|
public final java.util.concurrent.atomic.AtomicLong classLoadingTime
Remote code execution often results in classloading activity (more precisely, when the remote peer requests some computation on this channel, this channel often has to load necessary classes from the remote peer.)
This counter represents the total amount of time this channel had to spend loading classes from the remote peer. The time measurement doesn't include the time locally spent to actually define the class (as the local classloading would have incurred the same cost.)
public final java.util.concurrent.atomic.AtomicInteger classLoadingCount
classLoadingTime
.public final java.util.concurrent.atomic.AtomicLong resourceLoadingTime
classLoadingTime
public final java.util.concurrent.atomic.AtomicInteger resourceLoadingCount
classLoadingCount
public final Capability remoteCapability
Channel
.public static final int PIPE_WINDOW_SIZE
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, java.io.InputStream is, java.io.OutputStream os) throws java.io.IOException
java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os) throws java.io.IOException
java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header) throws java.io.IOException
java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header) throws java.io.IOException
java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header, boolean restricted) throws java.io.IOException
java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, Channel.Mode mode, java.io.InputStream is, java.io.OutputStream os, java.io.OutputStream header, boolean restricted, java.lang.ClassLoader base) throws java.io.IOException
name
- Human readable name of this channel. Used for debug/logging. Can be anything.exec
- Commands sent from the remote peer will be executed by using this Executor
.mode
- The encoding to be used over the stream.is
- Stream connected to the remote peer. It's the caller's responsibility to do
buffering on this stream, if that's necessary.os
- Stream connected to the remote peer. It's the caller's responsibility to do
buffering on this stream, if that's necessary.header
- If non-null, receive the portion of data in is before
the data goes into the "binary mode". This is useful
when the established communication channel might include some data that might
be useful for debugging/trouble-shooting.base
- Specify the classloader used for deserializing remote commands.
This is primarily related to getRemoteProperty(Object)
. Sometimes two parties
communicate over a channel and pass objects around as properties, but those types might not be
visible from the classloader loading the Channel
class. In such a case, specify a classloader
so that those classes resolve. If null, Channel.class.getClassLoader()
is used.restricted
- If true, this channel won't accept Command
s that allow the remote end to execute arbitrary closures
--- instead they can only call methods on objects that are exported by this channel.
This also prevents the remote end from loading classes into JVM.
Note that it still allows the remote end to deserialize arbitrary object graph
(provided that all the classes are already available in this JVM), so exactly how
safe the resulting behavior is is up to discussion.java.io.IOException
public Channel(java.lang.String name, java.util.concurrent.ExecutorService exec, CommandTransport transport, boolean restricted, java.lang.ClassLoader base) throws java.io.IOException
name
- See Channel(String, ExecutorService, Mode, InputStream, OutputStream, OutputStream, boolean, ClassLoader)
exec
- See Channel(String, ExecutorService, Mode, InputStream, OutputStream, OutputStream, boolean, ClassLoader)
transport
- The transport that we run Channel
on top of.base
- See Channel(String, ExecutorService, Mode, InputStream, OutputStream, OutputStream, boolean, ClassLoader)
restricted
- See Channel(String, ExecutorService, Mode, InputStream, OutputStream, OutputStream, boolean, ClassLoader)
java.io.IOException
public <T> T export(java.lang.Class<T> type, T instance)
Channel
by creating a remotable proxy.
All the parameters and return values must be serializable.
export
in interface VirtualChannel
type
- Interface to be remoted.Channel
, and calling methods on it from the remote side
will invoke the same method on the given local instance object.public void pin(java.lang.Object instance)
ExportTable.Entry.pin()
public void pinClassLoader(java.lang.ClassLoader cl)
public boolean preloadJar(Callable<?,?> classLoaderRef, java.lang.Class... classesInJar) throws java.io.IOException, java.lang.InterruptedException
This is a performance improvement method that can be safely ignored if your goal is just to make things working.
Normally, classes are transferred over the network one at a time, on-demand. This design is mainly driven by how Java classloading works — we can't predict what classes will be necessarily upfront very easily.
Classes are loaded only once, so for long-running Channel
,
this is normally an acceptable overhead. But sometimes, for example
when a channel is short-lived, or when you know that you'll need
a majority of classes in certain jar files, then it is more efficient
to send a whole jar file over the network upfront and thereby
avoiding individual class transfer over the network.
That is what this method does. It ensures that a series of jar files are copied to the remote side (AKA "preloading.") Classloading will consult the preloaded jars before performing network transfer of class files.
Beware that this method is not useful in all configurations.
If a RemoteClassLoader
has another RemoteClassLoader
as a
parent, which would be typical, then preloading
a JAR in it will not reduce network round-trips: each class load still has to call
loadClass
on the parent, which will
wind up checking the remote side just to get a negative answer.
classLoaderRef
- This parameter is used to identify the remote classloader
that will prefetch the specified jar files. That is, prefetching
will ensure that prefetched jars will kick in
when this Callable
object is actually executed remote side.
RemoteClassLoader
s are created wisely, one per local ClassLoader
,
so this parameter doesn't have to be exactly the same Callable
to be executed later — it just has to be of the same class.
classesInJar
- Class
objects that identify jar files to be preloaded.
Jar files that contain the specified classes will be preloaded into the remote peer.
You just need to specify one class per one jar.java.io.IOException
- if the preloading fails.java.lang.InterruptedException
public boolean preloadJar(java.lang.ClassLoader local, java.lang.Class... classesInJar) throws java.io.IOException, java.lang.InterruptedException
java.io.IOException
java.lang.InterruptedException
public boolean preloadJar(java.lang.ClassLoader local, java.net.URL... jars) throws java.io.IOException, java.lang.InterruptedException
java.io.IOException
java.lang.InterruptedException
public <V,T extends java.lang.Throwable> V call(Callable<V,T> callable) throws java.io.IOException, T extends java.lang.Throwable, java.lang.InterruptedException
Sends Callable
to the remote system, executes it, and returns its result.
call
in interface VirtualChannel
java.io.IOException
- If there's any error in the communication between Channel
s.java.lang.InterruptedException
- If the current thread is interrupted while waiting for the completion.T extends java.lang.Throwable
public <V,T extends java.lang.Throwable> Future<V> callAsync(Callable<V,T> callable) throws java.io.IOException
Similar to VirtualChannel.call(Callable)
but returns immediately.
The result of the Callable
can be obtained through the Future
object.
callAsync
in interface VirtualChannel
Future
object that can be used to wait for the completion.java.io.IOException
- If there's an error during the communication.protected void terminate(java.io.IOException e)
e
- The error that caused the connection to be aborted. Never null.public void addListener(Channel.Listener l)
Channel.Listener
.removeListener(Listener)
public boolean removeListener(Channel.Listener l)
public void addLocalExecutionInterceptor(CallableFilter filter)
CallableFilter
that gets a chance to decorate every Callable
s that run locally
sent by the other peer.
This is useful to tweak the environment those closures are run, such as setting up the thread context
environment.public void removeLocalExecutionInterceptor(CallableFilter filter)
addLocalExecutionInterceptor(CallableFilter)
.public void join() throws java.lang.InterruptedException
Channel
to be closed down.
The close-down of a Channel
might be initiated locally or remotely.join
in interface VirtualChannel
java.lang.InterruptedException
- If the current thread is interrupted while waiting for the completion.public boolean isRestricted()
public void setRestricted(boolean b)
public void join(long timeout) throws java.lang.InterruptedException
Channel
to be closed down, but only up the given milliseconds.join
in interface VirtualChannel
java.lang.InterruptedException
- If the current thread is interrupted while waiting for the completion.public void resetPerformanceCounters()
public void close() throws java.io.IOException
close
in interface VirtualChannel
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
java.io.IOException
- if the orderly shut-down failed.public void close(java.lang.Throwable diagnosis) throws java.io.IOException
diagnosis
- If someone (either this side or the other side) tries to use a channel that's already closed,
they'll get a stack trace indicating that the channel has already been closed. This diagnosis,
if provided, will further chained to that exception, providing more contextual information
about why the channel was closed.java.io.IOException
public java.lang.Object getProperty(java.lang.Object key)
setProperty(Object, Object)
.
These properties are also accessible from the remote channel via getRemoteProperty(Object)
.
This mechanism can be used for one side to discover contextual objects created by the other JVM
(as opposed to executing Callable
, which cannot have any reference to the context
of the remote Channel
.
public <T> T getProperty(ChannelProperty<T> key)
public java.lang.Object waitForProperty(java.lang.Object key) throws java.lang.InterruptedException
getProperty(Object)
but wait until some value is set by someone.java.lang.InterruptedException
public <T> T waitForProperty(ChannelProperty<T> key) throws java.lang.InterruptedException
java.lang.InterruptedException
public java.lang.Object setProperty(java.lang.Object key, java.lang.Object value)
getProperty(Object)
public <T> T setProperty(ChannelProperty<T> key, T value)
public java.lang.Object getRemoteProperty(java.lang.Object key)
public <T> T getRemoteProperty(ChannelProperty<T> key)
public java.lang.Object waitForRemoteProperty(java.lang.Object key) throws java.lang.InterruptedException
java.lang.InterruptedException
public <T> T waitForRemoteProperty(ChannelProperty<T> key) throws java.lang.InterruptedException
java.lang.InterruptedException
public java.io.OutputStream getUnderlyingOutput()
Channel
is not sitting on top of a stream pair.public ListeningPort createLocalToRemotePortForwarding(int recvPort, java.lang.String forwardHost, int forwardPort) throws java.io.IOException, java.lang.InterruptedException
recvPort
- The port on this local machine that we'll listen to. 0 to let
OS pick a random available port. If you specify 0, use
ListeningPort.getPort()
to figure out the actual assigned port.forwardHost
- The remote host that the connection will be forwarded to.
Connection to this host will be made from the other JVM that
this Channel
represents.forwardPort
- The remote port that the connection will be forwarded to.java.io.IOException
java.lang.InterruptedException
public ListeningPort createRemoteToLocalPortForwarding(int recvPort, java.lang.String forwardHost, int forwardPort) throws java.io.IOException, java.lang.InterruptedException
recvPort
- The port on the remote JVM (represented by this Channel
)
that we'll listen to. 0 to let
OS pick a random available port. If you specify 0, use
ListeningPort.getPort()
to figure out the actual assigned port.forwardHost
- The remote host that the connection will be forwarded to.
Connection to this host will be made from this JVM.forwardPort
- The remote port that the connection will be forwarded to.java.io.IOException
java.lang.InterruptedException
public void syncIO() throws java.io.IOException, java.lang.InterruptedException
java.io.IOException
- If the remote doesn't support this operation, or if sync fails for other reasons.java.lang.InterruptedException
public void syncLocalIO() throws java.lang.InterruptedException
VirtualChannel
syncLocalIO
in interface VirtualChannel
java.lang.InterruptedException
public java.lang.String getName()
public java.lang.String toString()
toString
in class java.lang.Object
public void dumpExportTable(java.io.PrintWriter w) throws java.io.IOException
java.io.IOException
public hudson.remoting.ExportTable.ExportList startExportRecording()
public long getLastHeard()
lastHeard
public static Channel current()
Channel
,
as well as during Callable.call()
is invoked.Copyright © 2013. All Rights Reserved.