Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
JavaCloak: Reecting on Java Typing for Class Reuse using Proxies Karen Renaud1 & Huw Evans2 1 University of South Africa ( [email protected]) 2 University of Glasgow ( [email protected]) We discuss problems caused by the limitations of Java's reection mechanism in supporting the specialisation of run-time program behaviour in JavaCloak. JavaCloak allows programmers to specialise the run-time behaviour of externally-developed code by using pre-generated source-level proxy objects. These proxy objects are of the same type as the original objects that they wrap. The runtime specialisation is achieved in two phases. Firstly, the programmer generates the proxies and tailors them to their local needs. The programmer then generates a JAR le of these proxy classes which is placed at the very start of the application's CLASSPATH variable. The virtual machine is thus diverted into loading the proxy classes instead of the original classes. At runtime the JavaCloak runtime system accesses the wrapped classes and mediates object creation and method calls across the proxy/original boundary. When code in the application requests a wrapped type, e.g., package1.T, the Java VM will load this from the JAR le. To gain access to the implementation in the original class, a specialised JavaCloak classloader, accessible from the proxy, loads the wrapped class from a location specied when the virtual machine is started. When a method is invoked on the proxy, the Java reection mechanism is used to forward this call onto the wrapped class and to handle the return of any result or exception objects. However, a number of implementation problems arise. For example, if the programmer is using a specialised classloader, they can bypass the JavaCloak facilities, and load the wrapped class from a dierent location than the JAR le. Java does not provide any support in its reection mechanism to divert all classloader requests via a central point, which would be possible if Java supported a meta-object protocol. Without this separation of concerns between the base and meta levels, it is not possible for the JavaCloak mechanism to integrate with other code in the general case. The second problem occurs because the proxy denes a number of extra methods, over and above those dened by the original class. If the original application reects over what it thinks is the original class and retrieves the signatures of all its methods, the list of methods that is passed back will be a superset of those expected. This may cause the application to fail. It is not possible to solve this problem inside JavaCloak as there is no way to programmatically control the information returned by the reection mechanism. Thirdly, if the original class denes a public, non-static eld, then this eld should be directly reachable from the proxy. However, the eld is actually dened on the real class and not on the proxy. Unfortunately, Java does not model eld access as method invocation, so there is no opportunity to redirect all accesses to the public eld via the proxy. This forces JavaCloak to assume a clean objectoriented programming model where the programmer only accesses class elds via method invocations, which reduces its exibility. By working at the Java-level, JavaCloak is forced to implement the proxy class and the wrapped class separately. This leads to two problems, the well known self problem and the encapsulation problem. The meaning of self (or this in Java programs) is dierent in the proxy and the real instance. Therefore, JavaCloak must adopt a forwarding model, whereas a delegation model would be preferable so that calls originating in the original object would be delegated to the proxy object. In terms of the encapsulation problem, the wrapping is only logical and this can therefore be broken. For example, the real object may pass back a direct reference to itself as part of the state of another object. A method can then be invoked on this object to obtain this direct reference, thus bypassing the proxy. This occurs because JavaCloak cannot reinterpret the meaning of this in the original object. Therefore, in the general case, the two instances must be treated dierently. Another problem is the forwarding of method calls from the proxy to the real object. In JavaCloak, all invocations on the public methods of an object are forwarded, including hashCode and equals. This means it is not possible to call these methods on the proxies themselves. Therefore, at the JavaCloak implementation level, these methods cannot be used to manage the proxy. This has required additional objects to be registered with the JavaCloak mechanism to operate as tokens for the proxy when calling across the proxy/wrapped boundary. In certain circumstances, the hashCode and equals could be applied to the proxy as the source code could be edited. However, this is not a solution in the general case as this cannot be guaranteed. In conclusion, the problems identied above highlight the inexibility of Java's reection mechanism. Java's reection mechanism is really an introspection mechanism, allowing the programmer to gain access to certain information about objects and classes. However, it does not allow the programmer to associate new behaviour with the basic building blocks of the language, such as method dispatch or redening the meaning of this. The above mentioned problems, when programming at the Java source-level, are insurmountable given the current denition of Java and current virtual machine implementations. It is not possible to provide a system to specialise the run-time behaviour of programs using source-code level proxy objects. Therefore, the programmer is forced to operate at the bytecode level. However, even operating at this level does not solve all problems as some policies are hard-wired into the virtual machine itself, e.g., bytecode verication policy. Therefore, to be truly exible, and to facilitate runtime specialisation at the Java-level, Java needs to dene a behavioural reection mechanism and future Java virtual machines need to give the programmer access, via this reection mechanism, to the internal policy decisions. The conclusion of this work is that providing this kind of facility at the Java level does not work in the general case and that the only solution currently available is to work at the bytecode level.