Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement JNDI, OSGI and Tomcat class loaders in JVM virtual machine 7

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to implement JNDI, OSGI and Tomcat class loaders in JVM Virtual Machine 7. The editor thinks it is very practical, so I share it with you for reference. I hope you can get something after reading this article.

Break the understanding of the parental delegation model JNDIJNDI

JNDI is Java naming and folder Interface (Java Naming and Directory Interface), which is one of the important specifications in J2EE specification. Many experts feel that without a thorough understanding of the meaning and function of JNDI, there is no real knowledge of J2EE, especially EJB.

So what exactly is the role of JNDI? / / it is most effective to read the article with questions.

To understand the role of JNDI, we can start from "what do we do without JNDI? what will we do with JNDI?" To explore this issue.

There is no JNDI practice:

When developing, the programmer knew that he was going to develop the application of the query MySQL database, so he coded a reference to the MySQL JDBC driver class and connected to the database by using the appropriate JDBC URL.

It looks like this code:

1. Connection conn=null; 2. Try {3. Class.forName ("com.mysql.jdbc.Driver", 4. True, Thread.currentThread (). GetContextClassLoader ()); 5. Conn=DriverManager. 6. GetConnection ("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue"); 7. 8. Conn.close (); 9.} catch (Exception e) {10. E.printStackTrace (); 11.} finally {12. If (connexion null) {13. Try {14. Conn.close (); 15.} catch (SQLException e) {} 16.} 17.}

This is a traditional practice and used to be a common practice for non-Java programmers (such as Delphi, VB, etc.).

This practice generally does not cause problems in the process of small-scale development, as long as programmers are familiar with Java language, JDBC technology and MySQL, they can develop corresponding applications very quickly.

The problem with the approach without JNDI:

1, the database server name MyDBServer, username and password may need to be changed, resulting in JDBC URL needs to be changed; 2, the database may be changed to other products, such as DB2 or Oracle, trigger JDBC driver package and class name need to be changed; 3, with the actual use of the terminal added, the original configuration of connection pool parameters may need to be adjusted; 4.

The solution:

Programmers should not care about "what is the detailed database background? what is the JDBC driver? what is the JDBC URL format? what is the username and password of the database?" Wait, these questions.

Programmers should write programs that have no references to JDBC drivers, no server names, no real username names or passwords-- not even database pools or connection management.

Instead, these issues are left to J2EE containers (such as weblogic) to configure and manage, and programmers simply need to reference these configurations and management.

From this, there is JNDI.

I can see that. It is for a core problem: to decouple, to develop a more maintainable and extensible / / system.

What you do after using JNDI:

First. Configure the JNDI parameters in the J2EE container to define a data source. That is, the JDBC reference parameter, set a name for the data source; then, in the program, refer to the data source through the data source name to ask the background database.

/ / the red word can be seen. JNDI is a function provided by the j2ee container

Detailed operations such as the following (take JBoss as an example):

1. Configure the data source

Under the D:\ jboss420GA\ docs\ examples\ jca folder of JBoss. There are many data source definition templates referenced by many different databases.

Copy the mysql-ds.xml file to the server you are using, such as D:\ jboss420GA\ server\ default\ deploy.

Change the contents of the mysql-ds.xml file so that it can correctly query your MySQL database through JDBC. For example:

1. 2. 3. 4. MySqlDS 5. Jdbc:mysql://localhost:3306/lw 6. Com.mysql.jdbc.Driver 7. Root 8. Rootpassword 9. 10. Org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter 11. 12. 13. MySQL 14. 15. 16.

Here, a data source named MySqlDS is defined. Its parameters include the URL of JDBC. Driver class name, username and password, etc.

2. Reference the data source in the program:

1. Connection conn=null; 2. Try {3. Context ctx=new InitialContext (); 4. Object datasourceRef=ctx.lookup ("java:MySqlDS"); / / reference data source 5. DataSource ds= (Datasource) datasourceRef; 6. Conn=ds.getConnection (); 7. 8. C.close (); 9.} catch (Exception e) {10. E.printStackTrace (); 11.} finally {12. If (connexion null) {13. Try {14. Conn.close (); 15.} catch (SQLException e) {} 16.} 17.}

The amount of programming code that uses JDBC directly or references a data source through JNDI is about the same, but today's programs don't have to worry about detailed JDBC parameters.

/ / decoupled. Expandable

After the system is deployed. Assume that the relevant parameters of the database change. You just need to configure the JDBC parameters in the mysql-ds.xml changes again, and just make sure that the name of the data source remains the same, then the program source code does not need to be changed.

This proves. JNDI avoids the tight coupling between the program and the database, and makes the application easier to configure and deploy.

Extensions to JNDI:

JNDI meets the requirements of data source configuration. The role is further expanded: all references to resources outside the system can be defined and referenced through JNDI.

/ / pay attention to what resources are

Therefore, in the J2EE specification, resources in J2EE are not limited to JDBC data sources.

There are many types of references, including resource references (which have been discussed), environmental entities, and EJB references.

In particular, the EJB reference exposes another key role of JNDI in J2EE: finding other application components.

The JNDI reference of EJB is very similar to the reference of JDBC resource. This is a very effective approach in an environment where services tend to be transformed. This type of configuration management can be performed on all components obtained in the application architecture, from EJB components to JMS queues and topics. Then simply configure a string or other object. This reduces maintenance costs arising from service changes over time, while simplifying deployment and reducing integration efforts. External resources ".

Summary:

The J2EE specification requires that all J2EE containers provide an implementation of the JNDI specification. / / sun really likes to make specifications. The role of JNDI in J2EE is a "switch"-- a common mechanism for J2EE components to ground to find other components, resources, or services at execution time. In most cases, the container that provides the JNDI provider can serve as a limited data store. This allows the administrator to set the execution properties of the application and have other applications reference these properties (the Java Management extension (Java Management Extensions,JMX) can also be used for this purpose). The primary role of JNDI in J2EE applications is to provide an indirection layer so that components can discover the resources they need without having to understand the indirectness.

In J2EE, JNDI is the glue that holds J2EE applications together. The indirect addressing provided by JNDI agrees to deliver scalable, powerful, and very flexible applications across enterprises.

This is the promise of J2EE, and after some planning and pre-consideration. This promise is fully achievable.

As can be seen from the above article:

1. The purpose of JNDI is to understand the lotus root, to develop more easy maintenance and easy extension. Applications deployed by easy.

2. JNDI is a specification proposed by a sun (similar to jdbc), and the detailed implementation is for each j2ee container provider. Sun simply requires that the j2ee container must have the function of JNDI.

3. The role of JNDI in j2ee system is "switch", which is a general mechanism for J2EE components to find other components, resources or services at execution time.

4. JNDI is found by the name of the resource, and the name of the resource is unique in the entire j2ee application (j2ee container).

As mentioned above, the parent delegation model is not a mandatory constraint model, but rather a classloader implementation recommended by Java designers to developers. Most classloaders in the Java world follow this model, but there are exceptions.

A "destruction" of the parent delegation model is caused by the defects of the model itself. The parent delegation well solves the problem of unifying the basic classes of each class loader (the more basic classes are loaded by the higher level loaders). The basic classes are called "basic" because they are always used as API called by user code, but things are often not absolutely perfect. What if the base class calls back the user's code again?

This is not impossible. A typical example is the JNDI service. JNDI is now the standard service of Java. Its code is loaded by the startup class loader (rt.jar put in at JDK 1.3), but the purpose of JNDI is to centrally manage and find resources. It needs to call the code of the JNDI interface provider (SPI,Service Provider Interface) implemented by an independent vendor and deployed under the Class Path of the application. But it is impossible to "recognize" this code by starting the classloader, because the user application class cannot be found in the search scope of the startup classloader, what should I do?

To solve this problem, the Java design team had to introduce a less elegant design: the thread context classloader (Thread Context ClassLoader). This class loader can be set through the setContextClassLoader () method of the java.lang.Thread class. If the thread is not set when it is created, it will inherit one from the parent thread. If it is not set in the global scope of the application, then this class loader is the application class loader (Application ClassLoader) by default.

With the thread context class loader, you can do something "fraudulent". The JNDI service uses this thread context class loader to load the required SPI code, that is, the parent class loader requests the subclass loader to complete the class loading action, which actually opens up the hierarchical structure of the parent delegation model to reverse the use of the class loader. In fact, it has violated the general principles of the parental delegation model, but there is nothing we can do about it. Basically all load actions involving SPI in Java use this approach, such as JNDI, JDBC, JCE, JAXB, JBI, and so on.

OSGI

At present, there are few learning resources or technical documents about OSGI technology in the industry. I searched a certain web site for "OSGI" books, and found that there were some, but the variety was pitifully small, and almost no one bought it.

Because of my work, I need to learn OSGI, so I have to try my best to learn OSGI actively. I will use words to record the whole process of learning OSGI, through collating books and video tutorials to let me know more about this technology, but also let comrades who need to learn this technology have a clear learning route.

We need to solve a few problems:

1. How to correctly understand and understand OSGI technology?

We can see from foreign materials or translated materials that the explanations and definitions of OSGi are translated literally, but the true meaning of OSGI is not necessarily the meaning of literal translation in Chinese. The interpretation of OSGI is Open Service Gateway Initiative, which literally translates to "initialization of open service entrances (gateways)". It sounds very confusing. What is service portal initialization?

So instead of literally translating this OSGI, let's put it another way to describe OSGI technology.

Let's go back to some of our previous development scenarios, suppose we use the SSH (struts+spring+hibernate) framework to develop our Web project, we do product design and development are sub-module, our sub-module purpose is to achieve "decoupling" between modules, a further purpose is to facilitate the control and management of a project.

After we modularize a project, we can hand over different modules to different developers to complete the development, and then the project manager puts the completed modules together and assembles them into a final product. Generally speaking, this is the basic situation in our development.

Then when we develop, we expect the function of the system, and divide the module according to the function of the system, that is to say, the function of this product or the demand of the customer is the important basis of the division.

But in the process of development, we have to keep in touch with each other, for example, the A module needs to get some data from the B module, and the B module may have to call some methods in the C module (in addition to the common underlying utility classes). So these modules are only a kind of division in the logical sense.

The most important thing is that we deploy the final project to a tomcat or jBoss server. So when we start the server, can we shut down a module or function of the project? Obviously, it can not be done, once the server starts, all modules have to start together and take up server resources, so the module can not be closed, assuming that it can be forcibly removed, it will affect other functions.

These are some of the limitations of our traditional modular development.

We have been pursuing a realm in software development, that is, the real "decoupling" and "separation" between modules, so that we will be more flexible in software management and development. even when deploying projects to customers can be more flexible and controllable. However, when we used SSH framework and other architectural patterns for product development, we could not meet this requirement.

So we "architects" or top technical experts are trying to explore and try for modular development, and then our OSGI technical specification arises at the historic moment.

Now our OSGI technology can meet what we said before: complete separation in different modules, not logical separation, but physical separation, that is to say, after running and deployment, some modules can be removed directly without stopping the server, and the functions of other modules will not be affected.

As a result, OSGI technology will become very important in the future, because it goes further than the SSH framework that is often used now on the way of module decoupling. This technology will greatly exceed the status of frameworks such as SSH in the future large-scale, high-access, high-concurrency Java modular development field, or project standardization management.

At present, some mainstream application servers, Oracle's weblogic server, IBM's WebSphere,JBoss, and Sun's glassfish server, all provide strong support for OSGI, all of which are implemented on the basis of OSGI technology. There are so many large vendors supporting OSGI technology, we can see the importance of OSGI technology. So OSGI is a very important technology in the future.

However, OSGI is still inseparable from the support of the framework, because OSGI itself also uses a lot of basic controls of frameworks such as spring (to implement functions such as AOP dependency injection), but which project does not rely on third-party jar?

Another "destruction" of the parent delegation model is caused by users' pursuit of program dynamics. "dynamic" here refers to some very "hot" nouns: hot code replacement (HotSwap), module hot deployment (HotDeployment), etc., to put it bluntly, it is hoped that the application program can be connected to the mouse and USB disk like our computer peripherals, and can be used immediately without restarting the machine. If there is a problem with the mouse or if you want to upgrade, change the mouse without stopping or rebooting.

For personal computers, a restart is no big deal, but for some production systems, a shutdown and restart may be classified as a production accident, in which case hot deployment is very attractive to software developers, especially enterprise software developers. The JSR-294 and JSR-277 specifications proposed by Sun lost to JSR-291 (that is, OSGi R4.2) in the competition with JCP. Although Sun is unwilling to lose the leadership of Java modularization and independently develops Jigsaw projects, OSGi has become a "de facto" Java modularization standard in the industry, and the key to OSGi's modular hot deployment is the implementation of its self-defined class loader mechanism.

Each program module (called Bundle in OSGi) has its own class loader. When a Bundle needs to be replaced, the Bundle is replaced with similar loaders to achieve hot replacement of the code.

In the OSGi environment, the class loader is no longer a tree structure in the parent delegation model, but is further developed into a more complex mesh structure. When a class loading request is received, OSGi will conduct a class search in the following order:

1) delegate classes that start with java.* to the parent class loader to load. 2) otherwise, the class in the delegate list is delegated to the parent class loader. 3) otherwise, delegate the class in the Import list to the classloader of the Bundle of the class Export. 4) otherwise, find the Class Path of the current Bundle and load it with your own class loader. 5) otherwise, find out whether the class is in its own Fragment Bundle, and if so, load it to the class loader delegated to Fragment Bundle. 6) otherwise, look for the Bundle of the Dynamic Import list and delegate it to the classloader of the corresponding Bundle to load. 7) otherwise, the class lookup fails.

In the above search order, only the first two points still conform to the parent delegation rules, and the rest of the class lookups are done in the horizontal class loader.

As long as there is sufficient meaning and reason, breaking through the existing principles can be regarded as a kind of innovation. Just as the classloader in OSGi does not conform to the traditional parent-delegated classloader, and there is still a lot of controversy about its additional high complexity in order to achieve hot deployment, there is a basic consensus among Java programmers: the use of classloader in OSGi is worth learning. If you understand the implementation of OSGi, you can master the essence of classloader.

Tomcat class loader and class isolation and sharing between applications

Users of Tomcat must have used its application deployment function, whether it is copying files directly to the webapps directory, modifying server.xml deployment in the form of a directory, adding virtual hosts, specifying a new appBase, and so on.

But when deploying an application, I don't know if you've ever noticed these points:

If multiple applications are deployed within a Tomcat, or even several similar versions are used within multiple applications, but they do not affect each other. How this is done.

If multiple applications use a similar version, can it be provided uniformly, not separately in each application, and take up memory?

Sometimes, when developing Web applications, servlet-api dependencies are added to pom.xml. Will your servlet-api jar be loaded when the class of the actual application is loaded?

These points mentioned above are implemented through class loader (ClasssLoader) in Tomcat and all kinds of application servers. Through this article, you can learn about the various class loaders provided within Tomcat, the loading methods of class and resources for Web applications, as well as its internal implementation principles. When you encounter similar problems, you are more confident.

Class loader

The Java language itself, and now some other languages based on JVM (Groovy,Jython, Scala …) Are compiling the code into class files to achieve cross-platform, write once, run anywhere. Finally, these class files, in the application, are loaded into the JVM virtual machine and started to work. The component that loads the class file into JVM is what we call a classloader. As for the abstraction of class loader, it can face more forms of class data provision, such as network, file system and so on.

The ClassNotFoundException and NoClassDefFoundError that are common in Java are what the classloader tells us.

The Servlet specification points out that the container is used to load the class loader of the Servlet in the Web application, allowing the loading of resources located in the Web application. But it is not allowed to rewrite java., javax. And the class implemented by the container. meanwhile

The class loader obtained by using Thread.currentThread.getContextClassLoader () in each application is the class loader that distinguishes the application from other applications, and so on.

According to the Servlet specification, each application server manufacturer implements it on its own. So like some other application servers, Tomcat provides a variety of class loaders so that different class repositories can be used when the class within the application server and the deployed Web application class files run in the container.

In Java, classloaders are organized in a parent-child tree. With the exception of Bootstrap, there is a parent class loader. (the parent classloader is written here instead of the parent classloader, not to load X, but to avoid confusion with the parent class in Java.) generally, when the classloader needs to load a class or resource file, he will first delegate to his parent classloader and let the parent classloader load first, and then load it on his own path if not. This is what people often call parental delegation, that is, delegating the request for class loading to parent.

But... Well, we need to pay attention here.

Class loading for Web applications is different from the parent delegate above.

Mainstream Java Web servers (that is, Web containers), such as Tomcat, Jetty, WebLogic, WebSphere, or other servers not listed by the author, implement their own defined class loaders (usually more than one). Because of a fully functional Web container, you need to solve the following problems:

1) the Java class libraries used by two Web applications deployed on the same Web container can be isolated from each other. This is the most basic requirement. Two different applications may rely on different versions of the same third-party class library, and only one copy of a class library in a server cannot be required. The server should ensure that the class libraries of the two applications can be used independently of each other.

2) the Java class libraries used by two Web applications deployed on the same Web container can be shared with each other. This requirement is also common. For example, users may have 10 applications organized using spring deployed on the same server. If 10 copies of Spring are stored in separate directories of each application, it will be a great waste of resources-- this is not mainly a waste of disk space, but means that class libraries are loaded into the memory of the Web container when they are used, if the class libraries cannot be shared. The method area of the virtual machine is prone to the risk of overexpansion.

3) the Web container needs to ensure that its security is not affected by the deployed Web application as much as possible. At present, there are many mainstream Java Web containers themselves implemented in the Java language. Therefore, the Web container itself has the problem of class library dependency. in general, for security reasons, the class library used by the container should be independent of the application's class library.

4) most Web containers that support JSP applications need to support HotSwap. We know that JSP files eventually have to be compiled into Java Class before they can be executed by virtual machines, but JSP files are much more likely to be modified at runtime than third-party class libraries or Class files of the program itself because of its plain text storage. And ASP, PHP and JSP web applications also do not need to restart after modification as a great "advantage", so the "mainstream" Web containers will support the hot replacement of JSP generated classes, of course, there are "non-mainstream", such as running in the production mode (Production Mode) of the WebLogic server will not deal with changes in JSP files by default.

Due to the above problems, when deploying Web applications, a single Class Path can not meet the needs, so all kinds of Web capacity "coincidentally" provide several Class Path paths for users to store third-party class libraries, which are generally named "lib" or "classes". Class libraries that are placed in different paths have different access ranges and service objects. Usually, each directory has a corresponding custom class loader to load the Java class libraries placed in it. Now, take the Tomcat container as an example to see how Tomcat specifically plans the structure of the user class library and the class loader.

In the Tomcat directory structure, there are three sets of directories ("/ common/", "/ server/" and "/ shared/") to store the Java class library, and you can also add the Web application's own directory "/ WEB-INF/". The meaning of placing the Java class library in these directories is as follows:

① is placed in the / common directory: the class library can be used by Tomcat and all Web applications.

② is placed in the / server directory: the class library is available to Tomcat and is not visible to all Web applications.

③ is placed in the / shared directory: the class library is common to all Web applications, but is not visible to Tomcat itself.

④ is placed in the / WebApp/WEB-INF directory: the class library can only be used by this Web application and is not visible to Tomcat and other Web applications.

In order to support this set of directory structure, and to load and isolate the class libraries in the directory, Tomcat has customized several class loaders, which are implemented according to the classical parent delegation model, and their relationship is shown in the following figure.

Cdn.xitu.io/2017/5/8/0dddae151e8fe1eba5db1a35d2b7b9b2?imageView2/0/w/1280/h/960/format/webp/ignore-error/1 ">

The three class loaders with a gray background above are the default class loaders provided by JDK, and the role of these three loaders has been introduced. CommonClassLoader, CatalinaClassLoader, SharedClassLoader, and WebappClassLoader are class loaders defined by Tomcat, which load the Java class libraries in / common/, / server/, / shared/, and / WebApp/WEB-INF/, respectively. There are usually multiple instances of WebApp class loader and Jsp class loader, each Web application corresponds to a WebApp class loader, and each JSP file corresponds to a Jsp class loader.

As you can see from the delegate relationship in the figure, the classes that CommonClassLoader can load can be used by CatalinaClassLoader and SharedClassLoader, while the classes that CatalinaClassLoader and SharedClassLoader can load themselves are isolated from each other. WebAppClassLoader can use the classes that SharedClassLoader loads into, but the WebAppClassLoader instances are isolated from each other.

The loading scope of JasperLoader is only the .Class file compiled by this JSP file, and it appears in order to be discarded: when the Web container detects that the JSP file has been modified, it will replace the current instance of JasperLoader and realize the HotSwap function of the JSP file by building a new Jsp class loader.

For version 6.x of Tomcat, the instances of Catalina ClassLoader and Shared ClassLoader will not be established until the server.loader and share.loader entries of the tomcat/conf/catalina.properties configuration file are specified, otherwise the instances of Common ClassLoader will be used where these two classloaders are used, and these two loader entries are not set in the default configuration file. So Tomcat 6.x naturally merges / common, / server, and / shared into a / lib directory by default, where the class libraries are equivalent to those in the previous / common directory.

This is an improvement made by the Tomcat design team to simplify most deployment scenarios, and if the default settings do not meet the needs, users can re-enable the loader architecture of Tomcat 5.x by modifying the configuration file to specify server.loader and share.loader.

The implementation of the Tomcat loader is clear and easy to understand and uses the officially recommended "orthodox" way of using the classloader. If, after reading the above case, the reader can fully understand the intention of the Tomcat design team to arrange the loader architecture in this way, it shows that they have roughly mastered the "mainstream" use of classloaders. Then the author might as well ask the reader another question for readers to think about: a scenario was mentioned earlier, if 10 Web applications are organized and managed with Spring. You can put Spring into the Common or Shared directory for these programs to share. If Spring wants to manage the classes of user programs, it naturally needs to be able to access the classes of user programs, and the user's programs are obviously placed in the / WebApp/WEB-INF directory, so how does the Spring loaded by CommonClassLoader or SharedClassLoader access user programs that are not within its loading scope? If you have studied the parent delegation model in the virtual machine loader mechanism, I believe the reader can easily answer this question.

Analysis: if you follow the mainstream parent delegation mechanism, it is obviously impossible for the classes loaded by the parent loader to access the classes loaded by the subclassloader. The classloader is propagated through thread context mentioned above in the classloader section.

The answer is to use the thread context class loader, which allows the parent class loader to request a subclass loader to complete the class loading action.

Looking at the spring source code, it is found that the Classloader used to load the spring class is obtained through Thread.currentThread (). GetContextClassLoader (), and when the thread is created, it will default to setContextClassLoader (AppClassLoader), that is, the thread context class loader is set to always get the AppClassLoader (WebAppClassLoader in Tomcat) subclass loader to load bean, and any thread can get WebAppClassLoader to getbean through getContextClassLoader ().

This is the end of this article on "how to implement JNDI, OSGI and Tomcat class loaders in JVM Virtual Machine 7". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report