Java remote class loading and light client (fat or thin in the Program)

Source: Internet
Author: User

Web development is so good, HTML is used so much, mainly because of convenient deployment and fast updates. The disadvantage of applications is the complexity of updates. Through this article, the application can be deployed as easily as the web. Easy to use.

 

As mentioned in the previous article, Java programs only rely on bytecode. Modifying the class file read/write mode can implement code encryption. The so-called "bytecode" is only a byte sequence, not necessarily a classFile. You can also remotely obtain bytecode to implement class loading so that the Code does not exist on the client. This not only provides higher security, but also has some additional advantages. Next, let's take a look at how to implement it.

 

In this article, the open-source framework netty of JBoss is used for communication. This is an asynchronous communication framework. Strictly speaking, remote class loading is not implemented. netty is used only because I am familiar with it and can be replaced by other communication methods (such as HTTP ).

 

The logic of remote loading is not difficult: the client initiates a loading request and notifies the full class name to be loaded. The server retrieves the bytecode of the corresponding class file from the local resource and returns it to the client, the next load is the same as the local load. The following is the server code (for details about netty usage, refer to the demo on the official website. This article does not explain too much and only provides the logic processing code ):

The client request only contains a string with a full class name. Cyptdatacache is a soft referenced map of byte []. It is used to cache the loaded bytecode sequence to reduce repeated file reads from the hard disk. The red box is the code that constructs the return value. The return value is a byte array with the following structure:

The bytecode file is stored in the. \ resource \ directory of the server, and can be encrypted or not (for example, the client must have a corresponding encryptor. See the previous article ). The reason why the returned value adds a full class name header is due to netty'sAsynchronousCommunication features. If you use the HTTP synchronization method, you can directly return the bytecode. If the requested class cannot be found, it is represented by a special byte 0xff (-1.

 

The client is a little more complex. First, define some communication-related objects:

 

Clch is the remote connection object encapsulated by netty. Ready indicates whether the connection is initialized successfully. The other three are designed to cope with the asynchronous features of netty: We cache the sent class loading requests to the remotetasklist object and listen to this object at the same time, the server return values are also stored in the value of remotetasklist.

 

The connection initialization code is as follows. gjvmclassloadclient is a custom initialization class and its function is to initiate a connection. For implementation of this class, see the netty demo source code.

The following method is used to initiate a load request:

Clch. Write is used to send remote requests. Then, through a time-limited loop listener, once a returned value is found, the bytecode is obtained from the remotetasklist, And the decrypted (if encrypted) method returns the value. As mentioned earlier, the asynchronous features of netty are not suitable for remote class loading. The loop here is an asynchronous to synchronous "expediency Plan", which is not strictly logical and may cause some extra latency.

 

After a request is sent, the returned value is processed using the following code:

Obtain the full class name from the header information of the returned value, and store the subsequent bytecode in the remotetasklist. Netty communication is implemented in its own communication thread. The previous circular code is actually the main thread waiting for the response from the communication thread. The last two sentences of the above Code implement a storage mode. You can choose whether to store the remote bytecode locally. You do not need to obtain it remotely at the next startup.

 

Now the entire loading process is complete. To enable remote loading during the loading process, you can rewrite sun. Misc. lanuncher $ appclassloader. loadclass. The added code is as follows (see the previous article ).

Also, pay attention to all embedded RT. jar user-defined classes use the namespace of the system class (sun. misc. *), including the related classes of netty, the default Org. JBoss. netty. * Change The namespace to sun. misc. netty. * (you must recompile the netty source code. It is not acceptable to directly reference the jar package ). The question about the JVM system class loading policy and namespace will be further discussed in subsequent articles.

 

After remote class loading is used, you only need to package a simple guide code when the project is released, and the logic code is placed under the Resource Directory of the server. This enables a "Light client ", this makes the business space almost no space occupied. When the project is running, the bytecode is directly loaded from remote to localMemoryTo further enhance the security (it is much more difficult to crack the static bytecode by blocking communication or memory analysis). If the project is updated, you only need to replace the server bytecode, the client can be automatically updated after being restarted to simplify project version maintenance.

 

The aforementioned "storage mode" also provides an additional feature: Dynamic class extraction. Third-party jar packages are used in the development process, and sometimes only some of the classes are used. For example, referencing the entire jar package is cumbersome, and it is difficult to determine which classes are useful manually. In this case, remote loading in the storage mode is suitable, and the classes used will be automatically "Extracted" to the local device.

 

Remote class loading also has some disadvantages. The most obvious difference is that the startup speed slows down (even if the effects of asynchronous synchronization are ignored). This can only be weighed between "lightweight" and "loading speed" through the combination of several loading modes; in addition, the Java System class itself cannot be customized for loading (at least this solution in this article), such as Java. AWT. *. The reason is that the defineclass method filters out the namespace of the full class name. A package name starting with Java. will throw "Java. Lang. securityexception", which is a JVM protection measure for the system class. However, Rt. jar is larger than 40 MB, and only a part of a single project is used. Therefore, the above dynamic class extraction for the system class is also a practical requirement. Subsequent articles will discuss the underlying implementation of Java System class name filtering and the feasibility of bypassing this filtering policy.

 

(If you are interested in or have any questions about the content of this article, add group 291694807 for discussion)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.