Modular java: Dynamic modularity

Source: Internet
Author: User
Tags bind garbage collection reflection tomcat log4j

In the previous article "Modular Java: Static modularity," we discussed how to build a Java module and deploy it as a separate jar. The example in this article gives a client and a server bundle (both in the same VM), and the client finds the server through the factory method. In this example, the factory instantiates a known class, and of course it can use reflection to get a service implementation; Spring is a massive use of this technology to bind the spring objects together.

Before we discuss dynamic services, it is necessary to review the classpath, because one of the differences between standard Java code and modular Java code is how dependencies are bound at runtime. After that, we'll talk a little bit about class garbage collection, and if you're already familiar with it, you can skip that part.

Bundle ClassPath

For a normal Java program, only one classpath--starts the one that the application uses. The path is usually specified with the-classpath option on the command line, or by CLASSPATH environment variables. The Java class loader scans this path when parsing classes at runtime, whether the process is statically (compiled into code) or dynamically (using reflection and Class.forName ()). However, multiple class loaders can be used at run time, and Web application engines such as jetty and Tomcat use multiple ClassLoader to support application hot deployment.

In OSGi, each bundle has its own class loader. Classes that need to be accessed by other bundle are delegated (delegated) to the class loaders of these other bundle. Therefore, although in traditional applications, classes from the Logging class library, client, and server jar are loaded by the same classloader, they are all loaded by their class loaders in the OSGi module system.

As a result, it is possible for a VM to have multiple classloader, which may have objects of different classes with the same name. That is, in the same VM, a class called COM.INFOQ.EXAMPLE.APP, its different versions can be exported at the same time by Com.infoq.example Bundle's version 1th and 2nd. Client Bundle version 1 uses the 1th version of the class, and client version 2 uses the 2nd version of the class. This is quite common in modular systems; In the same VM, some code may need to load an old version of a class library, while the code for the update point (in another bundle) requires a new version of the class library. Fortunately, OSGi manages this dependency transfer for you to ensure that no more problems arise from incompatible classes.

Garbage collection of Classes

Each class has a reference to its class loader. So if you want to access these classes from different bundle, you need not only a reference to the class instance, but also a reference to the class loader for that class. When a bundle holds another bundle class, it will also fix the bundle in memory. In the example in the previous article, the client is pinned to the server.

In a static world, it doesn't matter whether you're fixing your classes to another class (or class library), because there's no change. However, in a dynamic world, it is possible to replace a class library or tool with a new version at run time. This may sound a bit complicated, but it appears early in the Web application engine for hot-deployment applications (such as Tomcat, first published in 1999). Each Web application is bound to a version of the Servlet API, and when it stops, the ClassLoader that loads the Web application is discarded. When a Web application is deployed again, a new class loader is created and the newer class is loaded. As long as the servlet engine does not maintain references to legacy applications, these classes are reclaimed by the garbage collector like other Java objects.

Not all class libraries are aware of possible class leaks in Java code, like memory leaks. A typical example is the log4j addappender () call, which, once executed, binds your class to the log4j bundle lifecycle. Even if your bundle stops, log4j still references the dimension to Appender and continues to send log events (unless the bundle calls the Removeappender () method appropriately at the stop).

Find and bind

In order to be dynamic, we need to have a mechanism to find services rather than hold them permanently (lest bundle stop). This is accomplished by using a simple Java interface and Pojo, known as services (note that they are not related to Ws-deathstar or any other XML underlying architecture; they are ordinary Java objects--plain old Java Objects).

The typical factory implementation is to use some form of class name obtained from the properties file, and then instantiate the corresponding class with Class.forName (), and OSGi is different, it maintains a ' service registrar ', which is actually a map list containing the class name and service. In this way, the OSGi system can use Context.getservice (getservicereference ("Java.sql.Driver")) instead of Class.forName (" Com.example.JDBCDriver ") to obtain a JDBC drive. This frees the client code to be aware of any particular client implementation; Instead, it can bind any available drivers at run time. Porting to a different database server is very simple, just stop a module and start a new module; The client does not even need to reboot or change any configuration.

This is done because the client only needs to know the APIs for the services it needs (essentially interfaces, although the OSGi specification allows other classes to be used). In the above case, the interface name is java.sql.Driver; The interface instance returned is a specific database implementation (it is not necessary to understand which classes are encoded there). In addition, if the service is unavailable (the database does not exist, or the database is temporarily stopped), then this method returns null to indicate that the service is not available.

For full dynamic, the return result should not be cached. In other words, you need to call GetService again whenever you need a service. The framework performs caching operations at the bottom, so there is no significant performance problem. But importantly, it allows the database service to be replaced online with a new service, and if there is no cached code, the next time the client is called, it is transparently bound to the new service.

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.