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

What does JVM mean?

2025-03-04 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

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

Editor to share with you what JVM means, I believe that most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article, let's go to understand it!

1. Introduction of JVM

Before introducing JVM, take a look at the process of .java files from coding to execution:

The whole process is that the x.java file needs to be compiled into a x.class file, loaded into memory by a class loader, then interpreted and compiled by an interpreter or instant compiler, and finally handed over to the execution engine to operate the OS hardware.

The content from the classloader to the execution engine is JVM.

JVM is a cross-language platform. As you can see from the figure above, what is actually running on JVM is not a .java file, but a .class file. This leads to the idea that JVM is a cross-language platform. It can not only run java programs, but can run on it as long as the programming language can be compiled into .class files recognized by JVM.

So besides java, there are many languages that can run on JVM, such as JRuby, Groovy, Scala, Kotlin, and so on.

In essence, JVM is a virtual computer through software, it has its own instruction set and its own operating system.

So Oracle gave JVM a set of JVM specifications, and Oracle also gave his implementation. Basically, it is the most widely used java virtual machine implementation, called Hotspot. Using java-version, you can view:

Some large and large companies will also develop their own JVM virtual machines, such as TaobaoVM on Taobao, J9-IBM of IBM, MicrosoftVM of Microsoft, and so on.

2. JDK, JRE, JVM

JVM should be clear that it is a virtual machine running .class files. JRE is a runtime environment, including JVM and java core class libraries, which cannot run without a core class library.

JDK includes JRE and some toolsets used by developers.

So the overall relationship is JDK > JRE > JVM.

III. Class loading process

Class loading is a very important process of JVM work. We know that .class is a file that exists on the hard disk. How to load it into memory? this question is often asked in interviews. So you have to open the gap with other programmers and reflect differentiation, and this problem needs to be understood.

The process of class loading is actually divided into three steps: Loading (load), Linking (connection), and Initlalizing (initialization).

The second step Linking is divided into three small steps: Verification (verification), Preparation (preparation), and Resolution (parsing).

3.1 Loading

Loading loads the .class bytecode file into memory and converts the data into runtime data in the method area, generating a java.lang.Class class object in the heap to represent the class as an access entry for these types of data in the method area.

3.2 Linking

To put it simply, Linking is to merge the information of the original class definition into the JVM runtime state. It is divided into three small steps.

3.2.1 Verification

Verify that the loaded class information conforms to the standards of the class file to prevent malicious information or byte information that does not conform to the specification. It is an important guarantee for the running security of JVM virtual machine.

3.2.2 Preparation

Create static variables in a class or interface, and initialize static variables to assign default values. To assign a default value is not to assign an initial value, such as static int i = 5, this step is to assign I to 0 instead of 5. Assigning a value of 5 is a later step.

3.2.3 Resolution

Convert the symbolic references used in the constant pool of class files into direct memory addresses that can be accessed directly.

3.3 Initlalizing

This step actually executes the code logic of the class initialization clinit () (class constructor), including the action of static field assignment and the execution of logic within the static code block (static {}) in the class definition. When you initialize a class, you find that the parent class has not been initialized yet, then initialize the parent class first. The virtual machine ensures that the clinit () method of a class is properly locked and synchronized in a multithreaded environment.

Class loader

This is the whole process of class loading. The final step, Initlalizing, is to load the class through the class loader. I'm going to talk about the class loader alone here, because this is a key point.

The classloader in Java is divided from top to bottom:

Bootstrap ClassLoader (boot classloader) ExtClassLoader (extended classloader) AppClassLoader (application classloader)

From the class diagram, you can see that ExtClassLoader and AppClassLoader are both subclasses of ClassLoader.

So if you want to customize a class loader, you can inherit the ClassLoader abstract class and override the methods in it. We'll talk about what method to rewrite later.

5. Parental appointment mechanism

After talking about classloaders, how do these classloaders work? As for the parental appointment mechanism, I may have heard of it more or less, and it doesn't matter if I haven't heard of it. I'm going to talk about it.

It is mentioned above that there are three Bootstrap,ExtClassLoader,AppClassLoader classloaders. The working mechanism is as follows:

What is the logic of loading classes? the core code can be found in the JDK source code. If you are interested in the loadClass () of the abstract class ClassLoader class, you can take a look at the source code:

Protected Class loadClass (String name, boolean resolve) throws ClassNotFoundException {

Synchronized (getClassLoadingLock (name)) {

/ / First, check if the class has already been loaded

Class c = findLoadedClass (name)

If (c = = null) {

Long T0 = System.nanoTime ()

Try {

If (parent! = null) {

/ / if there is a classloader in the upper layer, recursively go up and look for the classloader in the upper layer

C = parent.loadClass (name, false)

} else {

C = findBootstrapClassOrNull (name)

}

} catch (ClassNotFoundException e) {

/ / ClassNotFoundException thrown if class not found

/ / from the non-null parent class loader

}

/ / if none of the upper layers can find the corresponding class

If (c = = null) {

/ / If still not found, then invoke findClass in order

/ / to find the class.

Long T1 = System.nanoTime ()

/ / load it yourself

C = findClass (name)

/ / this is the defining class loader; record the stats

Sun.misc.PerfCounter.getParentDelegationTime () .addTime (T1-t0)

Sun.misc.PerfCounter.getFindClassTime () .addElapsedTimeFrom (T1)

Sun.misc.PerfCounter.getFindClasses () .increment ()

}

}

If (resolve) {

ResolveClass (c)

}

Return c

}

}

In fact, the whole logic is very clear, in order to better understand, I would like to draw a picture for you to better understand:

Seeing here, you should have a clear understanding of the process of the parent appointment mechanism. The point is, why use the parental appointment mechanism?

If the interviewer asks this question, be sure to answer the key word: security.

Dialectical by anti-dialectics. Assuming that I do not use the parent delegation mechanism, then I can customize a class loader, and then I write a java.lang.String class to load it with a custom class loader. It turns out that java itself has a java.lang.String class, so the uniqueness of the class can not be guaranteed, which will bring hidden dangers to the security of the virtual machine. Therefore, it is necessary to ensure that a class can only be loaded by the same class loader in order to ensure the security of the system class.

VI. Custom class loader

Custom class loader, as mentioned above, can follow suit and customize a class to inherit ClassLoader abstract classes. Which method should be rewritten? The loadClass () method is a method that loads a class, so why don't you just override this?

If you rewrite loadClass (), that proves you've thought about it, but it's not quite right, because rewriting loadClass () breaks the logic of the parent delegation mechanism. The findClass () method in the loadClass () method should be overridden.

The findClass () method is the way the custom class loader loads the class.

What about the source code of the findClass () method?

Obviously this method is for subclass rewriting, and the permission modifier is also protected. If you don't override it, you will throw an exception that the class cannot be found. If you have studied the design pattern, you should be able to see that the template pattern is used here. So we can customize the class loader to override this method. Let's do it!

Create a CustomerClassLoader class that inherits the findClass () method of the ClassLoader abstract class.

Public class CustomerClassLoader extends ClassLoader {

/ / the path of the class file on disk

Private String path

/ / initialize the path of the class file through the constructor

Public CustomerClassLoader (String path) {

This.path = path

}

/ * *

* load classes

*

* @ full path of the param name class

* @ return Class

* @ author Ye hongzhi

, /

@ Override

Protected Class findClass (String name) throws ClassNotFoundException {

Class clazz = null

/ / get class file and convert it to bytecode array

Byte [] data = getData ()

If (data! = null) {

/ / convert the bytecode array of class into an instance of Class class

Clazz = defineClass (name, data, 0, data.length)

}

/ / return Class object

Return clazz

}

Private byte [] getData () {

File file = new File (path)

If (file.exists ()) {

Try (FileInputStream in = new FileInputStream (file))

ByteArrayOutputStream out = new ByteArrayOutputStream ();) {

Byte [] buffer = new byte [1024]

Int size

While ((size = in.read (buffer))! =-1) {

Out.write (buffer, 0, size)

}

Return out.toByteArray ()

} catch (IOException e) {

E.printStackTrace ()

Return null

}

} else {

Return null

}

}

}

This is done, so let's test it and define a Hello class.

Public class Hello {

Public void say () {

System.out.println ("hello.java")

}

}

Use the javac command to compile to a class file, as shown in the following figure:

Finally, write a main method to run the test:

Public class Main {

Public static void main (String [] args) throws Exception {

String path = "D:\ mall\\ core\\ src\\ main\\ java\\ io\\ github\\ yehongzhi\\ classloader\\ Hello.class"

CustomerClassLoader classLoader = new CustomerClassLoader (path)

Class clazz = classLoader.findClass ("io.github.yehongzhi.classloader.Hello")

System.out.println ("use classloader:" + clazz.getClassLoader ())

Method method = clazz.getDeclaredMethod ("say")

Object obj = clazz.newInstance ()

Method.invoke (obj)

}

}

Running result:

VII. Sabotage the parental appointment mechanism

When you see this, you must be very confused. Didn't we just talk about the parent appointment mechanism in order to ensure the security of the system, why destroy the parent appointment mechanism?

Review the parent delegation mechanism, you should remember that the underlying class loader has been delegating the upper class loader, if the upper class loader has already loaded, it does not need to load, the upper class loader does not load itself. This highlights a defect of the parent delegation mechanism, that is, only the child's class loader can delegate the parent's class loader, instead of using the parent's class loader to delegate the child's class loader.

Then you will ask, what happens when the parent's classloader delegates the child's classloader?

There is a real scenario in which the database driver of JDBC is loaded. There is an interface Java.sql.Driver in JDK that all JDBC drivers need to implement. The implementation class of Driver interface is provided by major database vendors. Then the problem arises: DriverManager (in JDK's rt.jar package) loads various implementation classes that implement the Driver interface, and then manages them uniformly, but DriverManager is loaded by the Bootstrap class loader and can only load files under the lib directory under JAVA_HOME (you can see the first diagram of the parent delegation mechanism above), but the implementation class is provided by the service provider and loaded by AppClassLoader This requires Bootstrap (upper class loader) to delegate AppClassLoader (lower class loader), which destroys the parent delegation mechanism. This is just one of the scenarios, and there are many other examples of breaking the parental delegation mechanism.

So how to destroy the parental appointment mechanism?

The simplest thing is to customize the classloader. As mentioned earlier, the findClass () method is rewritten in order not to break the parent delegation mechanism, so if I want to break the parent delegation mechanism, I will rewrite the loadClass () method to directly change the logic of the parent delegation mechanism. Rewriting this method is not recommended after JDK1.2. So provide the following way. Use the thread up and down file class loader (Thread Context ClassLoader). This class loader can be set through the setContextClassLoader () method of the java.lang.Thread class, and if it is not set when the thread 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 defaults to the AppClassLoader class loader.

So what is the way in which JDBC destroys the parental appointment mechanism?

Of course, the context file class loader is used, and the SPI mechanism is used, which is decomposed step by step.

The first step is that Bootstrap loads the DriverManager class and calls the initialization method in the static code block of the DriverManager class.

Public class DriverManager {

Static {

LoadInitialDrivers ()

Println ("JDBC DriverManager initialized")

}

}

The second step is to load all the implementation classes of the Driver interface, get a collection of Driver implementation classes, and get an iterator.

The third step is to look at the ServiceLoader.load () method.

Step four, look at the iterator driversIterator.

Then keep looking, and you will see a magical place.

The constant value PREFIX is:

Private static final String PREFIX = "META-INF/services/"

So we can find this file in the mysql driver package:

Find the implementation class of the interface through the file name, which is the SPI mechanism of java. So far, the case has been solved, my lord!

As a warm man, I'll just draw a picture and sum up the whole process:

The above is all the contents of this article "what does JVM mean?" Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

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

Internet Technology

Wechat

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

12
Report