ࡱ> egd{ Mbjbjzz 4f`D#22T:t?#?#?#:::::::$<>9:%k ?#%%9:M N:8*8*8*%p:8*%:8*8*;89@(B&89d:0:8D?'D?(9D?94?#Z#@8*#4 $?#?#?#9:9:P)?#?#?#:%%%%D??#?#?#?#?#?#?#?#?#2 R: 15-440: Distributed Systems Project #2: Design and Implementation of a RMI Facility for Java Credits Although this handout was prepared locally, this project was designed by  HYPERLINK "http://www.dcs.qmw.ac.uk/~kohei" Kohei Honda and published among the support materials for the Coulouris, et al textbook. Prof. Honda is a member of the Department of Computer Science, Queen Mary and Westfield College, University of London. He authored the source code provided on the project page. Overview This project asks you to design and implement a Remote Method Invocation (RMI) facility for Java. In other words, you are asked to provide a mechanism by which objects within one Java Virtual Machine (JVM) can invoke methods on objects within another JVM, even if the target object resides within a JVM hosted by a different, but network accessible, machine. Pedagogy This project is designed to reinforce your understanding of the basic challenges facing the developers of middleware, and the techniques used to overcome them. Specifically, we hope that this project will reinforce your understanding of the following: Naming objects (or programs) that reside among many hosts Locating objects (or programs) within many hosts Marshalling methods (or procedures) and their parameters Constructing a natural and largely transparent abstraction for the application developer using lower-level network abstractions, e.g. sockets Since this project is Java-specific, we do hope that youll take some time to consider Javas native JVM facility and to consider the design decisions made by its implementers. Needless to say, in many ways Javas own RMI might be a good inspiration for the RMI that you design and implement. By doing so, we hope that youll gain some valuable insights: A hands-on and in-depth understanding of RMI in Java A considered and critical understanding of both the design decisions made by the developers of Javas RMI and the trade-offs present in these decisions The Requirements The requirements are, if open-ended, very straight-forward. Without using Javas RMI facility, which includes everything in the java.rmi package, design and implement an RMI facility for Java. Once this is complete, prepare a professional-looking report that describes your design, the major design decisions, including trade-offs, and anything that is broken or incomplete. The report does not have to be large or fancy. Rather than counting pages or investing time in intricate figures, concentrate on effectively communicating to us those things that we have asked, with the fewest possible words and simplest figures. You Cant Do It All We recognize that there will be components of the facility that you simply wont have time to complete. In general we expect your solution to implement the following elements: the ability to name remote objects, e.g., remote object references the ability to invoke methods on remote objects, including those methods that pass and/or return remote objects references and those methods that pass and/or return references to local objects. The ability to locate remote objects, e.g. a registry service We dont expect you to create all of the tools that would be part of a commercial package. For example, the following would be nice, but arent required: A stub compiler (this is a bit time consuming but mechanical) The automatic retrieval of .class files for stubs (this isnt bad, if youve got a little extra time) A distributed garbage collector (we wouldnt even have time to think about this in the time provided) Furthermore, Javas native RMI facility is not perfect. For example, you might try playing with the .equals, clone(), or hashCode(). Youll soon discover that these dont work. We certainly dont expect you to fix these but wed like for you to understand the limitations and the reasons that they exist. For things you would have liked to have done, but did not, we would like you to do three things: Ensure that these things are possible given the rest of your solution. For example, even if you dont implement a stub compiler, it should be possible to implement one without magic (or intuition). Provide a work-around so that we can test your project. For example, if you dont provide a stub compiler, prepare some examples for us for which you have hand-written the stubs. Document the not-yet-implemented components in your report, with as much of a description of their design as you have prepared. A Suggested Framework Although we are leaving the design completely up to you, we do want to suggest an approach for tackling this assignment. In particular, wed like to suggest that you take a very careful look at Javas native RMI mechanism and understand how it works and the trade-offs the designers made. Wed like to further suggest that you emulate what you like and rework what you dont. We suggest that you explore it not only through documentation, such as that provided by Sun, but also through experimentation, by writing RMI applications to illuminate the mechanisms and behaviors of Suns RMI. For those who take this approach, most of the rest of this document highlights several key aspects of Javas native RMI facility and offers some implementation ideas. It isnt an exacting definition it does take some liberties. But, it is a good model for what Javas RMI actually does. This document concludes with a plan of action that might be helpful for those following an implementation similar to this one. The Big Picture The figure below illustrates the model used by Javas native RMI facility. The components and interactions are described in the sections below.           Remote Object References Java identifies objects using references. References are nothing more than names for objects. Typical references, such as those contained within Javas primitive reference variables are local references. That is to say that these references are capable of naming object only within a single JVM. But, an RMI facility needs a way of naming objects that live within one JVM from another JVM. In otherwords, a remote object reference type is needed. Although this type is transparent from the application programmers perspective, you probably want to create a class to represent it it will be very useful internally. The attributes of a remote object reference will vary with your design, but you might want to consider including the IP address and port number of the remote host, a local reference or other identifier, and the name of the interface implemented by the remote object. Unless your remote object reference explicitly contains the local reference, youll also need a mapping table on the server that maps between the remote object reference and the local object reference. And, actually manipulating Java references is harder than it seems. Client-side Stubs As discussed in class, Java represents objects to remote callers by placing a proxy object, known as a stub, locally within the callers JVM. It is the job of this stub to handle the marshalling of the method invocation into a message, the delivery of the message to the communication module, and the reverse of this process, all the way to the client object, upon the methods return. There is at least one instance of the stub class for each remote object in use within the JVM. If there are several remote objects, even if they are of the same type, there are several different instances of the stub class, one for each. Each instance of the stub class contains the remote object reference for the object that it represents. In order to ensure that only one stub exist for each remote object, Javas RMI maintains a table that maps between the remote object reference and the local reference to the stub. If a stub has not already been created for a particular remote instance, it is created and registered in this table. If the class for the stub is not already available on the client, it can be downloaded from the server via HTTP. Server-side Skeletons In the original version of RMI, there was a server-side compliment to the stub, known as the skeleton. The skeleton, like the stub, was responsible for marshalling. Java 2 eliminated the need for the server-side skeletons. It did this by factoring this functionality a common component, which I call the proxy dispatcher. This was possible, because no part of the process is necessarily unique to the particular target object. The unmarshalling of the method call is a mechanical step which yields a local object reference, a method to invoke, and the parameters to this method. Once this is known, the process of invoking the method using the local reference is the same for all objects. And, the last step, the marshalling of the return value, is just as mechanical as the initial unmarshalling. The only trick is maintaining the opportunity for concurrency, without breaking anything, throughout the process. We suggest eliminating the server-side skeletons only if you are comfortable with doing so. It isnt a big deal if you do make use of skeletons in your design and it might make the RMI mechanism a little less complicated. Messages We strongly suggest developing a general format for representing messages between classes. These messages can include method invocations, return values, and exceptions. In other words, develop a message class to represent the communication that will need to cross the network. If you do this, you will be able to pass the necessary information into the constructor to create a new message, send this message object whole over the network to the other side, instantiate it, and ask it to unpack itself. If you dont do this, youll have to worry about parsing data from the network in several different places and this is no fun. If you want to use three different message types, you might want to consider using inheritance to avoid block-copying the implementation of common behaviors. Communications We strongly suggest that you develop a class to handle communications. Depending on your design, the same one might work for either side of the pipe or you might develop two different classes, one for each side. If you do decide two develop two different classes, you might find inheritance useful. If youve got time, you might want to consider developing a connection cache. It isnt uncommon to find that two different JVMs are chattering a good bit and it can get expensive to build up and tear down the session with each network connection. Pass by Value vs. Pass by Reference In Java, parameters are passed into methods and returned from methods by reference. This is problematic for an RMI facility, because not all objects can be remote objects not all JVMs are willing to expose any of their objects, never mind all of them. As a result, the RMI facility needs to determine which object can be passed by reference, and which cant. And, it needs to have some mechanism for handling those that cant be passed by reference. To address the first concern, Java has a very simple rule. Any object that is to be remotely accessible must be an instance of a class that implements the Remote interface. Objects that implement the Remote interface are passed by reference into methods and when they are returned from methods. Other objects are passed by value, in other words by creating local copies. Java passes object by value using a process known as serialization. Basically, this means that Java flattens out the object, copies it, and sends this copy to the other side. At the other side, the object is recreated from the serialized copy, and a reference to this recreated object is used. Java needs to have an objects .class file to reconstitute it from the serialized copy. In order to recreate an object from a serialized copy, the objects .class file is needed. To facilitate this, Java sends the URL for the .class file along with the serialized copy. If the recipient doesnt already have the .class file, it can download it via HTTP using the provided URL. The result of this process is that there are two copies one on each side. The clients JVM has one copy and the servers JVM has another. Each acts on its own copy. The object has been passed by value. When Java passes an object by reference, it does this by passing a remote reference to the object, along with the URL of the stub class. This enables the recipient to recreate the stub object just as it did objects passed by value. As before, if the recipient doesnt already have a copy of the defining .class file, it can download it using HTTP via the provided URL. The process of recreating a remote object or stub on the local system is called localization. Pass by value localizes the remote object, pass by reference localizes a stub for the remote object. You are welcome to use Javas serialization methods, writeObject() and ReadObject, which can be found in ObjectInputStream and ObjectOutputStream. But, these probably will not prove to be as effective as you would like, since they wont treat your remote object references specially. Failure and Exceptions Unlike local method calls, remote method calls can fail. As an example, the network could be down or partitioned. Javas native RMI handles this by requiring that all methods of remote objects throw RemoteException. This, in turn, requires that each use of a remote method catch the RemoteException. Finding Remote Objects Most remote objects are found when references to them are returned by methods invoked on other remote objects. But, for obvious reasons, this mechanism does not explain how all remote objects are found -- we need to find the first object somehow. Java does this using a mechanism known as the RMIregistry. Servers that create remote objects designed to be the first point of contact by a client can register these remote objects using bind() or rebind(), which take a common, URL-style name and the local reference to the object. Once that happens, a client can connect to the RMIregistry on that server and ask for an object by name. In return, the client will get a reference to the remote object. A client can also invoke the list() method on the RMIregistry, which will return an array containing the names of all of the registered objects. The RMIregistry isnt global, instead there is one per server. Clients need to connect to a particular servers RMIregistry, which can tell them only about the objects registered on the same server. One Possible Plan of Action Play with Javas RMI. Become comfortable with it. Test out example that include remote and local objects as parameters and return values. Take a look at ObjectInputStream and ObjectOutputStream. Write toy code capable of serializing an object, writing it to a file, recreating it, and using the new instance. Write toy code capable of serializing an object, sending it over a socket, recreating it at the other side, recreating it, and using the recreated copy. Write the RMIMessage class capable of encapsulating a method invocation. Test it out by marshalling a method invocation, unmarshalling it, and invoking it. Enhance the RMIMessage class so it can handle return values, and then exceptions, if applicable to your design. Test this out after each step. Write toy code which accepts a method invocation, marshals it using your RMIMessage, unmarshals it from your RMIMessage class, invokes the method on another class, marshals the return value, unmarshals the return value, and then returns the value Develop your RemoteObjectReference class Develop your 440Remote interface, make sure you can use getInterfaces() to determine if an object implements this interface. Write a sample class that implements the 440Remote interface. Write a very simple sample client stub by hand. This stub should accept a local reference and marshal the method invocation to a local instance of the object. If you are using server skeletons, write one for the sample remote class. Write your communication modules. At this point, dont use the network. Use a file. This is easier to monitor for debugging purposes. Get the whole process working without the network. Test, test, test, test it doesnt get easier with the network and there is no file to observe. Eliminate the file interaction and add in full-blown network interaction. Once this is done, youve actually got a working RMI. Implement a registry and add support for it. If you are interested add support to download the .class files using HTTP. If you are interested, add support for connection caching. If you are interested, write the RMI compiler Clean up everything Organize some of your test code, or produce some examples for us that demonstrate your work. Write your report. Grading In grading your project, we will consider the design and implementation of the RMI facility, as well as the report. The most important factor in your grade is the quality of what you have built from the perspective of the application programmer. The next most important factor is the quality of your analysis of your design and implementation, as expressed in your report. The third major grading consideration is the quality of your implementation and documentation from the perspective of a maintainer, peer, or review committee. Server Client lookup() of remote object reference RMIregistry seemingly local method invocation Object A Stub for R Proxy dispatcher or skeleton marshalling/unmarshalling and communications requests seemingly local method invocation Object B Object R local method invocation &i ` l SiQRUWXYZ[]_`chilmopqw|=PUe4 K $#%#8#''()?,@,I,g/w/11̻̻̻̻̻̻̻̻̻̻hkW56\!jhkWCJU\mHnHu hkW\ h|&\hkW0J5\jhkW5U\hkWh|& h|&5\ hkW5\F]^_hi ` a b k l h i  6 & F$a$STUij^!_`9:;gh & Fh^h & Fh23  ,-QRVWY[^_ & F_abcimprstuvw}~!!""$#%#7#8#$$$&&<'='''''' ) )[+\+?,@,I,J,`-a-..e/f/g/v/w/000111113344~6677p8q899::;;;;; ===&='=1 224445A54:B:;#;(;:;;;='=CAEAaAbAkEEEEE0F3F9F>J?JAJIJ_L`LpLLLLL0M1MTMiMMMMM׺窺h|& hkWCJhkW h|&5\h|&5CJ\hkW5CJ\h|&56CJ\hkW56CJ\hkW5CJ\ hkWCJ\ h|&\ hkW\hkW56\ hkW5\/'=">#>??@?CADAaAbAAA'B(BBB6C7CCCeDfD]E^EEEFFFF & FF0G1GGGPHQHHHIIMINIIIIIII+J,J@JIJJJ_L`LgLhLh^hgd|&gd|& & FhLoLpLLLLLLLLLLLLLLLM0M1MBMTMUM^M_MhMiMMMMMMh^hgd|&21h:p|&/ =!8"8#8$8% ^ 666666666vvvvvvvvv666666>6666666666666666666666666666666666666666666666666hH6666666666666666666666666666666666666666666666666666666666666666662 0@P`p2( 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p 0@P`p8XV~_HmH nH sH tH @`@ NormalCJ_HaJmH sH tH @@@  Heading 1$$@&a$5\DA`D Default Paragraph FontViV  Table Normal :V 44 la (k (No List 80@8 List Bullet5\6U@6 Hyperlink >*B*phPK![Content_Types].xmlN0EH-J@%ǎǢ|ș$زULTB l,3;rØJB+$G]7O٭V$ !)O^rC$y@/yH*񄴽)޵߻UDb`}"qۋJחX^)I`nEp)liV[]1M<OP6r=zgbIguSebORD۫qu gZo~ٺlAplxpT0+[}`jzAV2Fi@qv֬5\|ʜ̭NleXdsjcs7f W+Ն7`g ȘJj|h(KD- dXiJ؇(x$( :;˹! I_TS 1?E??ZBΪmU/?~xY'y5g&΋/ɋ>GMGeD3Vq%'#q$8K)fw9:ĵ x}rxwr:\TZaG*y8IjbRc|XŻǿI u3KGnD1NIBs RuK>V.EL+M2#'fi ~V vl{u8zH *:(W☕ ~JTe\O*tHGHY}KNP*ݾ˦TѼ9/#A7qZ$*c?qUnwN%Oi4 =3N)cbJ uV4(Tn 7_?m-ٛ{UBwznʜ"Z xJZp; {/<P;,)''KQk5qpN8KGbe Sd̛\17 pa>SR! 3K4'+rzQ TTIIvt]Kc⫲K#v5+|D~O@%\w_nN[L9KqgVhn R!y+Un;*&/HrT >>\ t=.Tġ S; Z~!P9giCڧ!# B,;X=ۻ,I2UWV9$lk=Aj;{AP79|s*Y;̠[MCۿhf]o{oY=1kyVV5E8Vk+֜\80X4D)!!?*|fv u"xA@T_q64)kڬuV7 t '%;i9s9x,ڎ-45xd8?ǘd/Y|t &LILJ`& -Gt/PK! ѐ'theme/theme/_rels/themeManager.xml.relsM 0wooӺ&݈Э5 6?$Q ,.aic21h:qm@RN;d`o7gK(M&$R(.1r'JЊT8V"AȻHu}|$b{P8g/]QAsم(#L[PK-![Content_Types].xmlPK-!֧6 0_rels/.relsPK-!kytheme/theme/themeManager.xmlPK-!0C)theme/theme/theme1.xmlPK-! ѐ' theme/theme/_rels/themeManager.xml.relsPK] 5Bfp| "E#" ! 5Bfp| "% Ef1M'.h_$0'=FhLMM()*+,-/012EX8$$@ # (  VB @ C D"?V  # "?  V  # "?  V  # "?  V   #  "?  V   # "?  \B   S D"?hB   s *D8c"?nB  0D8c"?\B  S D"? \B @ S D"?\B  S D"?V  # "? hB  s *D8c"?nB  0D8c"?\  3 "? \  3  "?   \  3 "? \  3  "?  \B  S D"?\B   S D"?\ ! 3  !"?  \ " 3 ""? \ # 3 #"? B S  ?RSTWY[\_cdefgijkmnpwxyz{E#"At" tft@tthnt''teV 5t gIgt<ItW+Wtt js+t,th;t 00t at at!Zt "tkkttyytty xz x{ x| x} x~ xEE9*urn:schemas-microsoft-com:office:smarttagsplace=*urn:schemas-microsoft-com:office:smarttags PlaceName=*urn:schemas-microsoft-com:office:smarttags PlaceType  )bj&0y!!""22223#3(3:3444 5Q6\6o7z78'888889::%:A;K;;;;;<<<<<<%=/=k====`DDDDEEEEEsy8=e2l222558 888==???@`DpDwDDDDDDDDEEE1E:EBEHEiEnEEE3333333333333333333%&__;;$%?$@$5'5C9E9b9E<f<^====1>3>>>>>AA,B?B_D`DfDhDnDpDDDDDDDDDDDDD/E1ESEUE]E_EgEiEEEE%&__;;$%?$@$C9E9==1>3>>>>>?B_D`DEIbtz{X;r3T$Rte#]e@޽w¯Z hh^h`OJQJo(^`OJPJQJ^Jo( ^`OJQJo(o pp^p`OJQJo( @ @ ^@ `OJQJo( ^`OJQJo(o ^`OJQJo( ^`OJQJo( ^`OJQJo(o PP^P`OJQJo(^`o()^`.pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.hh^h`o(.^`.pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.^`OJPJQJ^Jo( ^`OJQJo(o ^`OJQJo( P P ^P `OJQJo(   ^ `OJQJo(o ^`OJQJo( ^`OJQJo( ^`OJQJo(o ``^``OJQJo(^`o(.^`.pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.h^`o()h^`.hpLp^p`L.h@ @ ^@ `.h^`.hL^`L.h^`.h^`.hPLP^P`L.tetw{X;r3T]e         <                X*        ܂        <        "&*YR#{|&kW`DbD@_D_D_D_DE@UnknownG*Ax Times New Roman5Symbol3. *Cx Arial?= *Cx Courier New;WingdingsACambria Math"qh0g0gVб4 ,:"|4 ,:"|!8824>D>D3QHP?"&*2!xx 15-498: Distributed SystemsGregory Kesdengkesden(       Oh+'0`    ( 4@HPX15-498: Distributed SystemsGregory KesdenNormalgkesden2Microsoft Office Word@@4fIA@A@A4 ,:՜.+,D՜.+,` hp  Carnegie Mellon University|">D 15-498: Distributed Systems Title 8@ _PID_HLINKSAxdj http://www.dcs.qmw.ac.uk/~kohei  !"#$%&'()*+,-./012356789:;<=>?@ABCDEFGHIJKLMNOPQRSUVWXYZ[]^_`abcfRoot Entry FBh1Table4l?WordDocument4fSummaryInformation(TDocumentSummaryInformation8\CompObjr  F Microsoft Word 97-2003 Document MSWordDocWord.Document.89q