Common JVM problems

Keywords: Java

https://www.jianshu.com/p/bdd7663f69c2

Talk about what you know about classloader, what is parental delegation, and how to break it?

Idea: introduction to class loader → purpose / significance → what is parental delegation → how to break it

What is a class loader?

Class loader is a tool that loads the. Class bytecode file into JVM memory according to the specified fully qualified class name and converts it into a class object.

What class loaders are there? What is their relationship?

  • Bootstrap classloader: it is implemented by C + + language (for Hotspot) and is responsible for storing in < Java_ Load the class library in the home > \ lib directory or the path specified by the - Xbootclasspath parameter into memory.
  • Extension classloader: responsible for loading < Java_ Home > \ lib \ ext directory or all class libraries in the path specified by the java.ext.dirs system variable.
  • Application classloader: it is responsible for loading the specified class library on the user classpath. We can directly use this classloader. Generally, if we do not have a custom classloader, this loader is used by default.
  • Custom classloader is a user-defined class loader that can complete operations such as encrypting class bytecode.
    From top to bottom is the relationship between parent class loader and child class loader.
    ###What is the whole process of class loader? (method call + parameter passing)

Parent loader, parent class (loader), loader of a loader, and the relationship between them?


The above figure shows the loader with inheritance relationship and the parent-child relationship. Is it the parent loader in our mouth? You might as well see the following code.

As can be seen from the above figure, we use the Application Loader to load the self-defined classes. The loader of the application loader is null, maybe the bootstrap class loader, which we can't see. The parent of the Application Loader, we say, is also a loader, which is an extended class loader. The parent of the extended class loader, is not visible.
We have reason to conclude that the parent is a class loader with more execution permission. When the current class loader cannot complete the loading work, it depends on its dual gas; it is not an inheritance relationship with the current class or a loader relationship with the current class.

How does the parental delegation model work?

A one sentence summary of the process from child to parent and then from parent to child. (related to the loadClass() method above)
Each class loader will ask whether the class has been loaded in the current cache. If not, it will call the loading method to the parent loader and fall into recursion. When reaching the top startup class loader, if there is no class in the cache, it will ask the child loader to complete the loading operation and return.

Why should there be parental delegation?

Consider from two angles

  1. Security
    If you customize a class with the same name as the core class, such as java.lang.String, you may have hidden dangers if you load it directly instead of asking the parent loader whether it has been loaded.
  2. Convenience
    Avoid repeated loading
    ###How to break the parental delegation? How to do it?
    Inherit ClassLoader class,
    Override findClass() method
    Then create and load the class, pass the fully qualified class name, create an instance and call the method
//Inherit ClassLoader
public class T006_MSBClassLoader extends ClassLoader {
//Override findClass method
@Override
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
//Defines the specified file path
        File f = new File("c:/test/", name.replace(".", "/").concat(".class"));
//Use the byte array output stream to read the bytecode file and save it in the byte array
        try {
            FileInputStream fis = new FileInputStream(f);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int b = 0;
            while ((b=fis.read()) !=0) {
                baos.write(b);
            }
            byte[] bytes = baos.toByteArray();
            baos.close();
            fis.close();//You can write more rigorously
// We still need to rely on defineClass to do it according to the specific path, file byte stream and start and end position
            return defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.findClass(name); //throws ClassNotFoundException
    }
    public static void main(String[] args) throws Exception {
        ClassLoader l = new T006_MSBClassLoader();
        Class clazz = l.loadClass("com.mashibing.jvm.Hello");
        Class clazz1 = l.loadClass("com.mashibing.jvm.Hello");
        System.out.println(clazz == clazz1);
        Hello h = (Hello)clazz.newInstance();
        h.m();

        System.out.println(l.getClass().getClassLoader());
        System.out.println(l.getParent());
        System.out.println(getSystemClassLoader());
    }
}

What is lazy loading?

A strategy to load only when the class needs to be used.
However, the timing of initialization is strictly specified:

  • new, getstatic, putstatic, invokestatic (accessing static variables) instructions except accessing final variables (accessing final static memberVariable will not load)
  • java.lang.reflect makes reflection calls to classes
  • When initializing a subclass, the parent class initializes first
  • When the virtual machine starts, the main class to be executed must be initialized
  • The dynamic language supports java.lang.invoke.MethodHandle. The parsing result is ref_getstatic ref) putstatic Ref_ The class must be initialized when invokestatic's method handle

Posted by ari_aaron on Sat, 16 Oct 2021 11:34:21 -0700