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

Summary of basic knowledge of JVM

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

This article mainly explains "the summary of the basic knowledge of JVM". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn the basic knowledge Summary of JVM.

1. The relationship between JDK, JRE and JVM 1.1 JDK

JDK (Java Development Kit) is a collection of software development tools for developing Java applications, including Java runtime environment (JRE), interpreter (Java), compiler (javac), Java archive (jar), document generator (Javadoc) and other tools. To put it simply, if we want to develop Java programs, we need to install a version of the JDK toolkit.

1.2 JRE

JRE (Java Runtime Enviroment) provides the environment needed for the execution of Java applications, which consists of Java virtual machines (JVM), core classes, support files, and so on. To put it simply, if we want to run Java programs on a machine, we can install JDK or just JRE, which is relatively small.

1.3 JVM

Java Virtual Machine (Java virtual machine) has three meanings, which are:

JVM specification requirements

A concrete implementation (a computer program) that meets the requirements of the JVM specification

A JVM running instance will be created when a Java command is written at the command prompt to run the Java class. This is what we mean if we only remember JVM below. If we take the name of some kind of JVM, say Zing JVM, it means the second meaning above.

1.4 the relationship between JDK, JRE and JVM

In terms of scope, JDK > JRE > JVM:

JDK = JRE + development tools

JRE = JVM + class library

The development and running process of Java program is as follows:

We use JDK (call Java API) to develop Java programs, compile them into bytecode or packaging programs, and then use JRE to start a JVM instance, load, verify, execute Java bytecode and dependent libraries, and run Java programs.

On the other hand, JVM parses the Java bytecode of the program and dependent library and turns it into native code execution to produce the result.

1.5 what if I don't know in which directory the automatic installation / other people's installed JDK is located?

The simplest / most troublesome way to query is to ask the person concerned.

There are many ways to find, for example, you can use which, whereis, ls-l to trace soft connections, or the find command to find globally (which may require sudo permission), for example:

Jps-v

Whereis javac

Ls-l / usr/bin/javac

Find /-name javac

two。 Common performance index

Without quantification, there is no improvement

Analyze system performance problems, such as whether we have achieved our expected performance indicators, determine whether there are problems at the resource level, whether there are problems at the JVM level, whether there are problems with the key processing processes of the system, and whether the business processes need to be optimized.

Through the tool to collect the status and logs of the system, including management to collect internal indicators, monitor and obtain key performance index data, including pressure testing to get some relevant pressure test data and performance internal analysis data.

According to the analysis results and performance indicators, adjust the resource allocation, and continuously monitor and analyze to optimize the performance until the system requirements are met and the best performance state of the system is achieved.

2.1 in computer systems, performance-related resources are mainly divided into these categories:

CPU:CPU is the most critical computing resource of the system, which is limited in unit time, and it is also easy to have bottlenecks due to unreasonable business logic processing. Wasting CPU resources and excessive consumption of CPU resources are not ideal, so we need to monitor relevant indicators.

Memory: memory corresponds to the fast temporary storage space for data that can be directly used when the program is running, and it is also limited. The use process continues to apply for memory and release memory over time. Fortunately, JVM's GC helps us deal with these things, but if the configuration of GC is unreasonable, various problems, including OOM downtime, will occur after a certain period of time, so memory indicators also need to be paid attention to.

IO (Storage + Network): after CPU calculates the business logic in memory, in order to preserve it for a long time, it must be persisted through disk storage media. If the multi-machine environment, distributed deployment, and external provision of network service capabilities, then many functions also need to directly use the network. The IO of these two blocks will be slower than CPU and memory, so it is also the focus of our attention.

2.2 Common routines in performance optimization

Generally speaking, there are bottlenecks in performance optimization, and the bottlenecks follow the principle of 80-20. Since we make a list of all the slow factors in the whole process and sort them according to their impact on performance, then the top 20% of bottlenecks will account for at least 80% of the impact on performance. In other words, we give priority to solving the most important problems, so the performance is more than half better.

We usually first check whether basic resources have become a bottleneck. Depending on whether the resources are enough, as long as the cost permits, plus configuration may be the fastest solution, and it may also be the most cost-effective and effective solution. The system resources related to JVM are mainly CPU and memory. If a resource alarm / shortage occurs, it is necessary to evaluate the system capacity and analyze the reason.

Generally speaking, there are three dimensions to measure system performance:

Latency: generally measured is response time (Response Time), such as average response time. But sometimes the response time jitter is particularly severe, that is to say, the response time of some users is particularly high. At this time, we generally assume that we need to ensure that 95% of the users respond within an acceptable range, thus providing a good user experience for the vast majority of users. This is the 95 line of delay (P95, the average response time of 95 out of 100 user requests). Similarly, there are 99 lines. Maximum response time, etc. (lines 95 and 99 are more commonly used When users visit a large number of users, any jitter to the network may cause the maximum response time to become very large, the maximum response time is not controllable, generally not used).

Throughput (Throughput): generally, for transactional systems, we use transactions per second (TPS) to measure throughput, and for systems that query search classes, we can also use requests per second (QPS).

System capacity (Capacity): also known as design capacity, can be understood as hardware configuration, cost constraints.

Performance metrics can also be divided into two categories:

Business demand indicators: such as throughput (QPS, TPS), response time (RT), number of concurrency, business success rate, etc.

Resource constraint index: the consumption of resources such as CPU, memory, Izod O, etc.

2.3 performance tuning summary

The first step in performance tuning is to develop metrics, collect data, and the second step is to find bottlenecks, and then analyze and solve bottlenecks. Through these means, find the current performance limit. TPS and QPS, which are adjusted to the point that they can no longer be optimized, are the limit values. Knowing the limit, we can measure traffic and system pressure according to business development, so as to make capacity planning and prepare machine resources and expected expansion plans. Finally, in the daily operation of the system, continuous observation, gradually redo and adjust the above steps to improve the performance of the system for a long time.

We often say that "talking about performance without a scene is a hooligan". In the actual process of performance analysis and tuning, we need to comprehensively consider the cost and performance according to the specific business scenario, and use the most appropriate method to deal with it. If the performance of the system is optimized to 3000TPS, if it has been able to meet the needs of business development within the range of cost, then there is no point in spending a few more man-months to optimize to 3100TPS, nor does it make sense to spend twice the cost to optimize to 5000TPS.

Donald Knuth once said that "premature optimization is the root of all evil", and we need to consider optimizing the system at the right time. In the early stages of business development, quantity is small and performance is not so important. When we build a new system, we first consider whether the overall design is OK, whether the function implementation is OK, and then when the basic functions are almost the same (of course, whether the overall framework meets the performance benchmark may need to pass the POC (proof of concept) phase verification in the preparation phase of the project.) And finally consider the optimization of performance Because if you consider optimization in the first place, you can think too much and lead to overdesign. And before the completion of the main framework and functions, there may be relatively big changes, once optimized in advance, these changes may lead to the original optimization are invalid, but also need to be re-optimized, doing a lot of useless work.

3. Basic knowledge of JVM 3.1 Common programming language types

First of all, we can divide all kinds of programming into three basic categories from the bottom up: machine language, assembly language, and high-level language.

According to the definition in the article "Development and Application of computer programming language": computer programming language can realize the communication and communication between human and machine, and computer programming language mainly includes assembly language, machine language and high-level language. The details are as follows:

Machine language: this language mainly uses binary coding to send instructions, which can be quickly recognized by the computer, its flexibility is relatively high, and the execution speed is considerable, and there is a high similarity between machine language and assembly language. however, because of its limitations, there are certain constraints in use.

Assembly language: this language is mainly written with the abbreviation English as the symbol, and the ones compiled with assembly language are generally relatively concise Mini Program, which is more convenient in execution, but the assembly language is relatively lengthy in procedure, so it has a high error rate.

High-level language: the so-called high-level language is actually a general term after the combination of a variety of programming languages, which can integrate multiple instructions and turn them into a single instruction to complete the transport. it has been properly simplified in terms of detailed instructions and intermediate procedures, so the whole program is simpler and more operable, and this kind of coding is simplified. As a result, the requirements of computer programming for the professional level of the relevant staff are constantly relaxed.

3.2 High-level language classification

If divided according to the availability of virtual machines, high-level programming languages can be divided into two categories:

There are virtual machines: Java,Lua,Ruby, partial implementation of JavaScript, and so on.

No virtual machine: CMagic CentralPhoneMagnum Golang, and most common programming languages

If it is divided according to whether the variable has a definite type, or whether the type can be changed at will, the high-level programming language can be divided into:

Static types: Java,C,C++, etc.

Dynamic types: languages for all script types

If it is compiled or interpreted, it can be divided into:

Compiled and executed: CMagneClojureMagneKotlin, Swift... Wait

Interpretive execution: partial implementation of JavaScript and NodeJS,Python,Perl,Ruby... Wait

In addition, we can also classify according to language characteristics:

Process-oriented: CMagneBasicPascalreFortran and so on.

Object-oriented: caterpillar, Java, Ruby, and Smalltalk, etc.

Functional programming: LISP, Haskell, Erlang, OCaml, Clojure, F# and so on

Some can even be divided into pure object-oriented languages, such as Ruby, where everything is an object (not everything in Java is an object, such as the basic types int, long, etc., but their wrapper classes Integer and Long are objects). There are also languages that can be used as both compiled and scripting languages, such as Groovy.

3.3 about cross-platform

Now let's talk about cross-platform, why cross-platform, because we want to write code and programs, at the source code level or after compilation, can run on a variety of different system platforms, without the need to implement two sets of code for different points of each platform. Typically, we write a web program and naturally want to deploy it to the Windows platform, to the Linux platform, or even to MacOS systems. This is the ability to cross-platform, greatly save development and maintenance costs, and win praise in the commercial market.

From this point of view, generally speaking, interpreted languages are cross-platform, and the same script code can be interpreted and executed by interpreters on different platforms. But for compiled languages, there are two levels of cross-platform: source cross-platform and binary cross-platform.

1. Typical source code cross-platform (C++):

2. Typical binary cross-platform (Java bytecode):

As you can see, in C++, we need to compile a copy of the source code on different platforms to generate binary executables related to this platform before we can run on the corresponding platform. This requires that there are development tools and compilers on each platform, and the development libraries that each platform depends on need to be consistent or compatible. This has been very painful in past years and has been jokingly called "dependence hell". C++ 's slogan is "write once, compile everywhere (on different platforms)", but in fact, an error is reported as soon as it is compiled, and it becomes "write once, debug everywhere, look for dependencies everywhere, and change configuration". You can imagine how desperate it is to compile a code and find dozens of dependencies missing and can't find them everywhere, or find them that are incompatible with existing local versions.

Java language takes the lead in solving this problem through virtual machine technology. The source code only needs to be compiled once, and then the compiled class files or jar packages are deployed to different platforms, which can be executed directly through the JVM installed on these systems. At the same time, the dependent libraries (jar files) can be copied to the target machine together, and gradually there is a central Maven library that can be used directly on all platforms (similar to yum or apt ­get source in linux, homebrew in macos, modern programming languages generally have this kind of package dependency management mechanism: python's pip, dotnet's nuget,NodeJS 's npm,golang 's cargo, etc.). This enables the ability to have the same application run directly on different platforms.

Summarize the cross-platform:

Scripting languages are directly executed by interpreters of different platforms, which is called scripting across platforms. The differences between platforms are solved by interpreters on different platforms. In this way, the code is very general, but it needs to be interpreted and translated, and it is inefficient.

The code of compiled language is cross-platform, and the same code needs to be compiled into corresponding binary files by compilers of different platforms, and then distributed and executed. The differences between different platforms are solved by compilers. The compiled and generated files are executable instructions directly directed at the platform, and the running efficiency is very high. However, when compiling complex software on different platforms, relying on configuration may cause many environmental problems, resulting in high cost of development and maintenance.

The binary of a compiled language is cross-platform, and the same code is first compiled into a common binary file, and then distributed to different platforms, which is loaded and executed by the virtual machine runtime, which combines the advantages of the other two cross-platform languages. run on a variety of platforms conveniently and quickly, although it may be slightly less efficient than locally compiled type-like languages. These advantages and disadvantages are also the advantages and disadvantages of Java virtual machine.

3.4 about runtime (Runtime) and virtual machine (VM)

We have mentioned many times the Java runtime and the JVM virtual machine. To put it simply, JRE is the runtime of Java, including virtual machines and related libraries and other resources. It can be said that the runtime provides the basic environment for the program to run. JVM needs to load all the runtime core libraries and other resources at startup, and then load our application bytecode in order to make the application bytecode run in the JVM container.

But there are also some languages that do not have virtual machines, so when compiling and packaging, the dependent core libraries and other features are supported, statically packaged or dynamically linked to the program, such as Golang and Rust,C#. In this way, the runtime is combined with program instructions to become a complete application. The advantage is that there is no need for a virtual machine environment, and the disadvantage is that the compiled binaries cannot be directly cross-platform.

3.5 about memory management and garbage collection (GC)

Memory management is the life cycle management of memory, including memory application, compression, recycling and other operations. The memory management of Java is that the GC module of GC,JVM not only manages the recovery of memory, but also is responsible for the allocation and compression of memory.

4. Java bytecode

The bytecode in Java, known as bytecode in English, is the intermediate code format of the compiled Java code. JVM needs to read and parse the bytecode to perform the corresponding task. It consists of single-byte (byte) instructions and theoretically supports up to 256opcodes (opcode). In fact, Java uses only about 200 opcodes, and some opcodes are reserved for debugging operations.

The opcode, hereinafter called the instruction, is mainly composed of the type prefix and the operation name.

> for example, the'I 'prefix stands for' integer', so 'iadd' is easy to understand and means to add integers.

4.1 according to the nature of the instruction, it can be divided into four main categories:

Stack operation instructions, including instructions that interact with local variables

Program flow control instruction

Object operation instructions, including method call instructions

Arithmetic operation and type conversion instruction

In addition, there are instructions to perform specific tasks, such as synchronization instructions, instructions related to throwing exceptions, and so on.

4.2 object initialization instructions: introduction to new instruction, init and clinit

We all know that new is a keyword in the Java programming language, but in fact, there is also an instruction called new in bytecode. When we create an instance of the class, the compiler generates opcodes similar to the following:

```0: new # 2 / / class demo/jvm0104/HelloByteCode 3: dup4: invokespecial # 3 / / Method "": () V```

When you see new, dup, and invokespecial instructions together, you must be creating an instance object of the class! Why three instructions instead of one? This is because:

The new directive just creates the object, but does not call the constructor.

The invokespecial instruction is used to call some special methods, and of course the constructor is called here.

The dup instruction is used to copy the value at the top of the stack.

Because the constructor call does not return a value, if there is no dup instruction, after the method is called on the object and initialized, the Operand stack will be empty, something will go wrong after initialization, and the next code will not be able to process it.

When the constructor is called, another similar method is actually executed, even before the constructor is executed. Another possible method to execute is the static initialization method of the class, which cannot be called directly, but is triggered by these instructions: new, getstatic, putstatic or invokestatic.

4.3 Stack memory operation instruction

There are many instructions that can manipulate the method stack. Some basic stack instructions have also been mentioned earlier: they push values into the stack or get values from the stack. In addition to these basic operations, there are also instructions that manipulate stack memory; for example, the swap instruction is used to exchange the values of the two elements at the top of the stack. Here are some examples:

The most basic are dup and pop instructions.

The dup instruction copies the value of the element at the top of the stack.

The pop directive removes the topmost value from the stack.

There are also more complex instructions: for example, swap, dup_x1 and dup2_x1.

As the name implies, the swap instruction swaps the values of the two elements at the top of the stack, such as An and B swap positions (example 4 in the figure)

Dup_x1 will copy the value of the element at the top of the stack and insert it into the top two values (example 5 in the figure)

Dup2_x1 copies the values of the top two elements of the stack and inserts the top three values (example 6 in the figure).

Supplementary instructions for dup, dup_x1, dup2_x1 directives:

Dup instruction: the official statement is to copy the value at the top of the stack and push the copied value into the stack.

Dup_x1 directive: the official statement is to copy the value at the top of the stack and insert the copied value below the top two values.

Dup2_x1 instruction: the official statement is to copy a 64-bit value or two 32-bit values at the top of the stack and insert the copied values under a 32-bit value below the original value in the original order.

5. Arithmetic operation instruction and type conversion instruction

There are many instructions in Java bytecode that can perform arithmetic operations. In fact, a large part of the representation in the instruction set is about mathematical operations. For all numerical types (int, long, double, float), there are addition, subtraction, multiplication, division, and reverse instructions. What about byte and char boolean? JVM is treated as int. There are also some instructions for conversion between data types.

Type conversion occurs when we want to assign a value of type int to a variable of type long.

6. Method invocation instructions and parameter passing

Invokestatic, as the name implies, this instruction is used to call static methods of a class, which is also the fastest method invocation instruction.

Invokespecial, we've learned that the invokespecial instruction is used to call the constructor, but it can also be used to call private methods in the same class, as well as visible superclass methods.

Invokevirtual, if it is a specific type of target object, invokevirtual is used to call public, protected, and packaged private methods.

Invokeinterface, the invokeinterface instruction is used when the method to be called belongs to an interface.

> so what's the difference between invokevirtual and invokeinterface? This is really an easy question. Why do you need invokevirtual and invokeinterface instructions? After all, all interface methods are public methods, so can't you just use invokevirtual directly? This is done because of the optimization of method calls. JVM must parse the method before calling it

Using the invokestatic directive, JVM knows exactly which method to call: because the method is static, it can only belong to one class.

When using invokespecial, the number of lookups is small, and parsing is easier, so the runtime can find the methods you need more quickly.

Before JDK7, the bytecode instruction set of the ava virtual machine had only the four instructions mentioned above (invokestatic,invokespecial,invokevirtual,invokeinterface). With the release of JDK 7, invokedynamic instructions have been added to the bytecode instruction set. This new instruction is one of the improvements to the implementation of dynamically typed language (Dynamically Typed Language) support and is the basis for the implementation of lambda expressions supported later in JDK 8.

7. The life cycle and loading process of Java class loader class 7.1

The life cycle of a class in JVM has seven phases, namely, Loading, Verification, Preparation, Resolution, Initialization, Using, and Unloading. The first five parts (loading, validation, preparation, parsing, initialization) are collectively referred to as class loading. Let's talk about these five processes separately.

7.1.1 load

The load phase can also be called the "load" phase. The main operation of this phase is to get the byte stream in binary classfile format based on the well-known class fully qualified name, which is simply to find the "class file" in the file system / jar package / or anywhere. If the binary representation is not found, a NoClassDefFound error is thrown. The load phase does not check the syntax and format of classfile. The whole process of class loading is mainly completed by the class loading system of JVM and Java. Of course, the loading stage is completed by the cooperation of JVM and a specific class loader (java.lang.classLoader).

7.1.2 check

The first stage of the linking process is verification to ensure that the byte stream information in the class file meets the requirements of the current virtual machine and will not endanger the security of the virtual machine. The verification process checks the semantics of classfile, judges the symbols in the constant pool, and performs type checking. The main purpose is to determine the validity of bytecode, such as magic number, to verify the version number. VerifyError, ClassFormatError, or UnsupportedClassVersionError may be thrown during these checks. Because the validation of classfile is part of the link phase, you may need to load other classes during this process, and during the loading process of a class, JVM must load all its superclasses and interfaces. If there is a problem with the class hierarchy (for example, the class is its own superclass or interface, and it loops), JVM throws a ClassCircularityError. If the implemented interface is not an interface, or if the declared superclass is an interface, an IncompatibleClassChangeError is also thrown.

7.1.3 preparation

Then enter the preparation phase, which creates static fields, initializes them to standard default values (such as null or 0 values), and allocates the method table, which is the memory space used to allocate these variables in the method area. Note that no Java code is executed during the preparation phase.

For example:

Public static int i = 1

The value of I will be initialized to 0 in the preparation phase, and the assignment to 1 will be performed later in the class initialization phase; but if you use final as a static constant, the behavior of some JVM will be different:

Public static final int i = 1

The corresponding constant I will be assigned a value of 1 in the preparation phase, which is actually more puzzle. For example, other languages (C #) have a direct constant keyword const, which makes it easier to tell the compiler to replace it with a constant at the compilation stage, similar to macro instructions.

7.1.4 parsing

Then enter the optional parsing symbol reference phase. That is, the parsing constant pool, there are mainly the following four kinds: class or interface parsing, field parsing, class method parsing, interface method parsing.

To put it simply, in the code we write, when a variable references an object, the reference is stored as a symbolic reference in the .class file (equivalent to making an index record). In the parsing phase, it needs to be parsed and linked as a direct reference (equivalent to pointing to the actual object). If there is a direct reference, the target of the reference must exist in the heap. When you load a class, you need to load all the super classes and super interfaces.

7.1.5 initialization

The JVM specification makes it clear that class initialization cannot be performed until the first "active use" of a class. The initialization process includes executing:

Class constructor method

Static static variable assignment statement

Static static code block

If a subclass is initialized, the parent class is initialized first to ensure that the parent class is initialized before the subclass. So if you initialize a class in java, you must initialize the java.lang.Object class first, because all java classes inherit from java.lang.Object.

7.2 Class loading time

Now that we understand the loading process of the class, let's see when the initialization of the class will be triggered. The JVM specification enumerates the following triggers:

When the virtual machine starts, initialize the main class specified by the user, which is the class where the main method that starts the execution is located

When you encounter the new instruction to create a new instance of the target class, initialize the target class of the new instruction, that is, new a class.

When an instruction to call a static method is encountered, initialize the class in which the static method is located

When an instruction to access a static field is encountered, initialize the class in which the static field is located

The initialization of the subclass triggers the initialization of the parent class

If an interface defines a default method, initializing the class of the interface directly or indirectly will trigger the initialization of the interface.

When you use reflection API to make a reflection call to a class, initialize the class. As before, the reflection call is either instantiated or static, and all need to be initialized.

Initialize the class of the method that the MethodHandle points to when the MethodHandle instance is called for the first time.

Class initialization is not performed in the following situations:

Referencing the static field of the parent class through the subclass triggers only the initialization of the parent class, not the initialization of the subclass.

Defines an array of objects that does not trigger initialization of the class.

Constants are stored in the constant pool of the calling class during compilation. In essence, there is no direct reference to the class that defines the constant and does not trigger the class in which the constant is defined.

Getting the Class object through the class name does not trigger the initialization of the class, and Hello.class does not let the Hello class initialize.

When loading a specified class through Class.forName, the class initialization will not be triggered if the specified parameter initialize is false. In fact, this parameter tells the virtual machine whether to initialize the class. Class.forName ("jvm.Hello") loads the Hello class by default.

The initialization action (loaded but not initialized) is also not triggered by the default loadClass method of ClassLoader.

7.3 Class loading mechanism

The class loading process can be described as "getting the Class object that describes the class through the fully qualified name of a class a.b.c.XXClass", which is done by the class loader (ClassLoader). The advantage of this is that the subclass loader can reuse classes loaded by the parent loader. There are three kinds of class loaders that come with the system:

Start the classloader (BootstrapClassLoader)

Startup class loader (bootstrap class loader): used to load the core classes of Java, is implemented in native C++ code and does not inherit from the

Java.lang.ClassLoader (responsible for loading all class in jre/lib/rt.jar in JDK). It can be seen as included in JVM, and we can't get it directly at the code level.

Starts a reference to the classloader, so it is not allowed to manipulate it directly, if printed out is a null. For example, java.lang.String is loaded by the startup class loader

, so String.class.getClassLoader () returns null. But you can see later that you can influence what it loads through command-line parameters.

Extended class loader (ExtClassLoader)

Extension class loader (extensions class loader): it is responsible for loading the extension directory of JRE, lib/ext, or the class of the JAR package in the directory specified by the java.ext.dirs system property. The parent class loader that gets it directly in the code is null (because the startup class loader cannot be obtained).

Application class loader (AppClassLoader)

Application classloader (app class loader): it is responsible for loading the ­classpath or ­cp options from the Java command, the jar package specified by the java.class.path system property, and the classpath when the JVM starts. The application class loader can be obtained in the application code through the static method getSystemClassLoader () of ClassLoader. If not specifically specified, user-defined classes are loaded by this loader without using a custom class loader.

The class loading mechanism has three characteristics:

Parental delegation: when a custom class loader needs to load a class, such as java.lang.String, it is lazy and does not attempt to load it directly, but entrusts its own parent loader to load it first. if the parent loader finds that it has a parent loader, it will keep looking forward, so as long as the parent loader, such as the startup class loader, has loaded a class such as java.lang.String All subloaders do not need to load themselves. If none of the class loaders are loaded into the class with the specified name, a ClassNotFountException exception is thrown.

Responsible for dependencies: if a loader loads a class and finds that the class depends on several other classes or interfaces, it will also try to load those dependencies.

Cache loading: in order to improve loading efficiency and eliminate repeated loading, once a class is loaded by a class loader, it will cache the loading result and will not load repeatedly.

At this point, I believe you have a deeper understanding of the "summary of the basic knowledge of JVM". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

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