You design a Java RMI remote object by first:
- Writing an interface which extends
Remote
.
- Implementing a class which extends
RemoteClass
.
- Writing a class that extends
RemoteObject
.
- Writing an interface which implements
UnicastRemoteObject
.
- Running the rmiregistry.
In Java RMI the stub instance is
- Downloaded from the rmiregistry.
- Implemented by you, the programmer.
- Unable to access its skeleton until you call
activate()
.
- The implementation of the remote object's logic. That is, it is the one that actually implements the methods.
- Unnecessary since Java uses the JVM.
Say you have a reference to a remote object, you call some
methods on that object and then set it to
null
. What will happen to that object on the remote
server assume that you are the only one using it?
- It will get garbage collected.
- Nothing.
- It will get garbage collected when you call
delete()
on the object.
- It will be placed on the heap.
- It will get placed on the stack.
If you want to write the implementation of a remote interface
RemInt
, you must implement which one of the
following?
- A class that implements
RemInt
and extends UnicastRemoteObject
- A class that extends
RemInt
and implements UnicastRemoteObject
- A class that extends
RemInt
and extends UnicastRemoteObject
- A class that implements
RemInt
and implements UnicastRemoteObject
- A class that implements
RemInt
.
Given that the following code represents a remote object.
interface WidgetInt extends Remote{
public void justDoIt();
}
public class Widget implements WidgetInt
extends UnicastRemoteObject{
public void justDoIt(){
}
}
You would get a reference to this remote object by using which
line of code?
- Widget q = (Widget)Naming.Lookup(...);
- Widget q = Naming.Lookup(...);
- Widget q = (WidgetInt)Naming.Lookup(...);
- WidgetInt q = Naming.Lookup(...);
- WidgetInt q = (WidgetInt)Naming.Lookup(...);
If you ran an object server on machine "Bubbles" serving service
"SuperStrength" and the rmiregistry was on machine "Buttercup",
the rebind
call would need to use a parameter:
- This is a trick question. You cannot register a service with an rmiregistry on another machine.
/Bubbles/SuperStrength
/Buttercup/SuperStrength
/SuperStrength
/localhost/SuperStrength
In Java RMI, when we say that an object has been
exported, what do we mean?
- It has started to listen on a port for requests from the stub.
- It has been registered with the rmiregistry.
- It has loaded the stub class code into the rmiregistry.
- The stub instance has been transferred from the remote server to the client.
- The object has been sent to another client.
Which one of the following is not a way to export an RMI object?
- Call
Naming.exportObject()
.
- Create a new instance of an object that extends
UnicastRemoteObject
.
- Create a new instance of an object that extends
Activatable
.
- Call
UnicastRemoteObject.exportObject()
.
- Call
Activatable.exportObject()
.
Given the following code:
GradeManager remoteObject = Naming.lookup("the-right-thing-here");
Vector v = new Vector();
v.addElement("Mojo Jojo");
remoteObject.addStudents(v);
printVector(v);
public void addStudents(Vector v){
v.addElement("Gangrene gang");
return;
}
What will happen when the client code is run? Assume that
everything that is not show works properly and that the lookup
also works.
- It will print "Mojo Jojo"
- It will print "Mojo Jojo" and "Gangrene gang"
- It will throw an exception because we are trying to modify a non-remote argument.
- It will not compile because we are trying to modify a non-remote argument.
- It will not print anything but it will run.
In Java RMI, the job of the SecurityManager
is to:
- Make sure that loaded classes do not do things we don't want.
- Make sure the stub downloaded from the rmiregistry is the one we wanted to download.
- Make it impossible for a program to communicate across the Internet.
- Prevent the spread of viruses.
- Enable to formation of an event-based notification system for security warnings.
When called, the first thing that the Java RMI
Naming.lookup
function does is to:
- Construct a registry stub instance.
- Open a socket to the registry.
- Send a message to the registry.
- Open a socket to the desired object server.
- Determine if the requested object is local or remote.
If the JVM has an instance of an object for which it has not
loaded the its class file, it will look for this class file on
the
- First on the CLASSPATH, then on the codebase.
- CLASSPATH
- SOURCEPATH
- CLASSPATH and current directory
- Hard drive.
The program used to generate your stubs and skeletons in RMI is called
- rmic
- javac
- idlc
- stubc
- ssc
The Factory design pattern allows us to
- Determine at runtime the specific subtype of the object we will create.
- Create many instances of the same object.
- Distribute an object across the network.
- Make sure that only one remote instance of a particular object exists.
- Create many remote objects of the same type as a given non-remote object.
In RMI we use the Factory pattern when
- We want many instances of a remote object.
- We want to speed up remote object creation.
- We want to make the code more complex than it needs to be.
- We want to enable distributed garbage collection.
- We want to limit the number of object instances to one.
In Java RMI, dynamic code downloading allows the client of a
remote object to:
- Use the stub instance even if its class file is not on the CLASSPATH.
- Call a remote object even if its interface was not on the CLASSPATH.
- Download a remote object to the local machine for better performance.
- Download parts of an object to the local machine for better runtime performance.
- Download a stub instance from a remote repository.
Say two JVM's have slightly different definitions of a class
Money
. One of the machines creates an instance of
Money
and sends that instance to the other machine
as an argument in a remote method call. What will happen at the
other machine?
- It will use its local definition of the class to access the instance.
- It will dynamically download the class files from the first machine.
- It will raise an exception notifying the user about the mismatched classes.
- It will only be able to use the methods defined in the first machine's implementation.
- It will
An RMI Activatable
object is a remote object that:
- Will start running only after being invoked by a client.
- Can be made to run in various machines.
- Conserves resources by sharing its socket with all the other remote objects in the JVM.
- Can be activated by the object server at any time.
- Continuously runs in the background in case a client invokes one of its methods.
In order to use Activatable
objects you also need
to have which program running?
- rmid
- rmic
- javac
- activated
- daemon
A server that hosts Activatable
objects has a more
complicated start-up procedure than one with
UnicastRemoteObject
s because:
- It must create an
ActivationDesc
for each instance of an Activatable
object.
- It must register with the rmiregistry.
- It must start a program for each instance of an
Activatable
object.
- It must start an rmid for each instance of an
Activatable
object.
- Both cases are equally complicated (i.e., simple).
If you wanted to encrypt the RMI communications you would:
- Create a custom
RMISocketFactory
.
- Use the -RMIencrypt option at compile time.
- Pass a
CypherSuite
object to the Remote object constructor.
- Pass a
SSLSocket
object to the Remote object constructor.
- Rewrite all the methods to use encrypted arguments and return encrypted values.
If an RMI remote object server hosts many instances of various
objects which are being used by a few remote JVMs, how can we
reduce the number of sockets used?
- There is no need to do so since RMI re-uses the same socket for communication between any two JVMs.
- We can use the factory design pattern.
- We can have the clients garbage-collect all the stubs.
- We can define our own
SocketFactory
that uses compression sockets.
- We can use
Activatable
objects.
Which one of the following is not a question that you
should ask when designing the interface for your remote object
server?
- Does the implementation of the server require the use of third-party libraries?
- Does each instance of the server require
a shared or scarce resource?
- How well does the server replicate or
scale to multiple machines?
- Can a single server handle a typical
client interaction?
- How easy is it to make a server handle
multiple simultaneous clients?
Generally, you want to design your remote object interfaces such
that if an object server fails
- It affects as few clients as possible.
- All the clients have to be restarted.
- The rmiregistry does not need to be restarted.
- It only creates a bottleneck for non-serializable objects.
- There are other object servers that can maintain connectivity.
The other object servers cannot maintain connectivity.
Why do we sometimes prefer to use method objects when designing
an interface for a remote object?
- Because they allow us to add functionality without changing the interface.
- Because they can by dynamically downloaded from the client.
- Because regular objects do not contain the method synergy present in method objects.
- Because method objects enable cleaner, easier-to-use interfaces.
- We do not. Method objects should only be used by non-remote objects.
My new API leverages cross-platform method synergy! Yow!
When designing an interface for a remote object, should the
methods return an object, a primitive value, or nothing? Why?
- An object or nothing. The objects can carry more information with them.
- A primitive value because it uses less memory and indicates success.
- A primitive value or nothing because the use less memory.
- An object or a primitive value because we should always return something.
- An object because remote objects are usually assumed to return objects.
Which one of the following is not a reason why you should
not return a Vector
or ArrayList
in a
remote object method call?
- The client cannot easily determine what is inside them.
- They degrade perceived client performance.
- They increase performance variance.
- They involve a large, all-at-once network hit.
- They involve a larger single-client commitment on the
part of the server.
When designing a local object's interface it is good design to
use many small methods, this is not always a good idea for
remote objects because:
- Remote method calls are expensive.
- Remote object must use object methods.
- RMI cannot handle well an object with too many method.
- The time it takes to reply to a method grows linearly with the number of methods in the object.
- A large number of methods make the interface harder to understand.
In a remote object interface we want to have a lot of
descriptive methods because:
- They provide information about the server.
- They enable faster communications.
- They can describe their own functionality, thereby allowing dynamic code introspection.
- They do not need to throw
RemoteObjectException
.
- They return primitive values which makes them faster.
The general rule for choosing which exceptions your remote
object should throw is:
- Throw the most specific exception possible.
- Throw the most number of exceptions possible.
- Throw as few exceptions as possible.
- Throw only very general exceptions.
- Throw only exceptions that deal with communications issues.
In RMI a tie server is used when
- We want to implement a remote object that
extends another class but we still want to use
UnicastRemoteObject
.
- The object server does not have enough resources to handle all the outstanding objects.
- We want to provide extra reliability in case the main object server goes down.
- We are serving
Activatable
objects but do not want to bother using the rmi daemon
.
- We have a need to leverage the rmiregistry over a multi-paradigm solution.
In Java RMI the launch code's responsibility is to:
- Register the objects and start the object servers (if needed).
- Register the objects and initialize the clients.
- Register the objects, start the servers, and start the clients.
- Register the objects.
- Start the rmiregistry.
A client of an RMI remote object should set its reference to the
remote object to null
as soon as possible because:
- This reduces the load on the object server.
- It allows the local garbage collector to garbage-collect all related local objects.
- It allows the object to be sent to another client.
- This should not be done because there is always the possibility that we might want to use the remote object at some later time.
- It is good programming practice to always set a reference to null after using it once.
Given that a class has the following method defined for it
public static synchronized void yellSome(String s){
}
This means that:
- Only one thread can be executing this method at any one time.
- This is an illegal statement. It would be impossible to synchronize a static method.
- Only one thread can be executing an this method on every instance of the object (i.e., one thread per instance, max).
- This function can only be called once in the lifetime of the program.
- This function can be called by multiple threads simultaneously, as long as they make sure to grab the lock beforehand.
Simply synchronizing all the methods of an object is not enough
to ensure data integrity because:
- The client might assume that the value returned by one method continues to be correct when he access another method.
- It might still be possible for two threads to access the same method for the same object instance at the same time.
- A client could get around this by using an adapter object.
- Having so many synchronized blocks increases latency.
- You cannot synchronize all the methods of an object.
A lock expiry thread is used (in an RMI situation) for
- Expiring locks that are held by dead clients.
- Removing expired events without causing a deadlock with other expiry threads.
- Garbage-collecting clients whose references have been set to
null
.
- Verifying that no deadlocks are present in the object.
- Expiring locks that are causing deadlocks.
The code below is not thread-safe because:
public synchronized void insertIfAbsent(Vector vector,
Object object){
if (vector.contains(object)) {
return;
}
vector.add(object);
}
- It allows the same object to be inserted twice if two threads are using the object.
- It is thread-safe because the
Vector
class is thread-safe and it used the synchronized
keyword.
- It allows multiple threads to access the
insertIfAbsent
method on the same object instance.
- It allows multiple threads to access the
contains
method on the same object instance.
- It creates a deadlock whenever it is called.
Serialization can cause the loss of data integrity because:
- An object's parts could change while the object is being serialized.
- Not all objects can un-serialize without errors.
- Serialization only works for some objects.
- Different JVM's on different platforms have different serialization algorithms.
- Multiple threads might try to do serialization at the same time which could cause corruption of the serialization engine.
There is no "serialization engine".
When running the rmiregistry you must make sure that
- The stub classes are in its CLASSPATH
- The clients are running on the same machine.
- The
Naming.rebind
call is made by the registry.
- The
Naming.lookup
call is made by the registry.
- There are no other registries running on the LAN.
A good rule of thumb for building distributed object servers is:
- Keep them small.
- Include all needed functionality into one server.
- Always use synchronized methods.
- Implement multiple constructors.
- Leverage cross-platform functionality.
Does "Leverage cross-platform functionality" actually mean anything? No.