19 Ocak 2021 Salı

ClassLoader Sınıf Yükleme Sırası

Giriş
Java 8 - Java 9 geçişinde sınıfları yükleyen ClassLoader'lar biraz değişti ancak mantık hemen hemen aynı.
Genel anlamda şöyledir. ClassLoader  sınıf önce kendi önbelleğinde arar. Eğer yoksa bir üstteki ClassLoader'a yönlendirir. Üsttekiler yükleyemezse, ClassLoader kendisi yüklemeye çalışır
The class loader delegation model is the graph of class loaders that pass loading requests to each other. The bootstrap class loader is at the root of this graph. Class loaders are created with a single delegation parent and look for a class in the following places:

- Cache
- Parent
- Self
A class loader first determines if it has been asked to load this same class in the past. If so, it returns the same class it returned last time (that is, the class stored in the cache). If not, it gives its parent a chance to load the class. These two steps repeat recursively and depth first. If the parent returns null (or throws a ClassNotFoundException), then the class loader searches its own path for the source of the class.
Java 8

Java 9
Java 9 ile module yapısına geçildiği için biraz değişiklik oldu. Açıklaması şöyle.
Application class loader : The application class loader is typically used to define classes on the application class path. It's default loader for JDK modules that provide tools or export tool APIs.

Platform class loader : It is selected (based on security/permissions) by Java SE and JDK modules. For e.g. java.sql

Bootstrap class loader : It defines the core Java SE and JDK modules.
Java EE (Jakarta) Container ve Custom Classloader
Açıklaması şöyle.
First of all, Java EE containers (like Tomcat, GlassFish and so on) uses a custom ClassLoader (let calling it CW) for loading web application classes. Classes that are not part of the web application (like ThreadLocal and other JDK classes) are loaded by another ClassLoader (C0).

If a class loaded by C0 references something loaded by CW, this reference doesn't allow the garbage collector cleaning all the involved instances (not even when the application is undeployed!) and this will cause the ClassLoader leak. So, after a sequence of deployment and undeployment, your server will run out of memory.
Elimizde şöyle bir kod olsun.
public class MyCounter {
  private int count = 0;

  public void increment() {
    count++;
  }

  public int getCount() {
    return count;
  }
}

public class MyThreadLocal extends ThreadLocal<MyCounter> {
}

public class LeakingServlet extends HttpServlet {
  private static MyThreadLocal myThreadLocal = new MyThreadLocal();

  protected void doGet(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException, IOException {

  MyCounter counter = myThreadLocal.get();
  if (counter == null) {
    counter = new MyCounter();
    myThreadLocal.set(counter);
  }

  response.getWriter().println(
    "The current thread served this servlet " + counter.getCount()
    + " times");
    counter.increment();
  }
}
Bu kod Classloader leak'e sebep olabilir. Çünkü ServletKodu CW tarafından yüklenir. ThreadLocal ise C0 tarafından yüklenir. Uygulama undeploy edilse bile CW->kullanır->C0 olduğu için CW nesnesi silinemez.

Bootstrap ClassLoader Nedir?
Açıklaması şöyle. JVM ilk başlarken çalışır.
There is a bootstrap class loader written in native code which loads classes such as Object and ClassLoader.
Açıklaması şöyle
Every JVM implementation must have a bootstrap class loader. It loads core java API classes present in lib directory of jre folder of jdk. This path is popularly known as bootstrap path. It is implemented in native languages like C, C++. The bootstrap class loader is also known as Primordial ClassLoader in Java.
Bootstrap ClassLoader'a müdahale etmek mümkün

Örnek
Eğer kendi java.lang.Object sınıfımızı yazarsak ve kullanmak istersek Java 8'de şöyle yaparız
$ java -Xbootclasspath/p:. java.lang.Object
Hello world from custom java.lang.Object!
Java 9'da şöyle yaparız
java --patch-module java.base=<path>
Açıklaması şöyle.
When you try to load your version of the Object class at runtime, you stumble across the fact that you can’t load classes of the java.lang package (or any class whose qualified name starts with java.) through the class path in general.

Prior to Java 9, you would have to set up the bootstrap class path to include your version. Starting with Java 9, the class java.lang.Object must belong to the java.base module, which is loaded in an implementation specific manner. You’d have to use the --patch-module option to inject your own version.
Extension ClassLoader Nedir?
Açıklaması şöyle
It is child of bootstrap class loader. It loads the classes present in the extension directories ext(Extension path) or any other directory specified by the java.ext.dirs system property. It is implemented in java by the sun.misc.Launcher$ExtClassLoader class.
System/Application ClassLoader Nedir?
Açıklaması şöyle.  Bu sınıfın tam ismi "sun.misc.Launcher$AppClassLoader"
The loading of classes is done by 3 class loaders. The first one is the BootStrap ClassLoader that loads classes from the rt.jar. The highest priority is given to this class loader. The second one is the Extension ClassLoader which loads classes that are inside the ext folder (jre\lib). The third one is the Application ClassLoader which loads classes that are there on the classpath. The JVM follows Delegation-Hierarchy principle to load classes. First the class is loaded by the BootStrap ClassLoader. If not found, it is delegated to Extension ClassLoader. If not found, it is delegated to Application ClassLoader. If not found, the JVM will throw ClassNotFoundException.
Açıklaması şöyle.
It is child of extension class loader. It is responsible to load classes from application class path. It internally uses environment variable which mapped to java.class.path. It is also implemented in Java by the sun.misc.Launcher$AppClassLoader class.
Custom ClassLoader Nedir?
Açıklaması şöyle.
JVM has its own class loaders, but they load files from a local file system or hard drive location. Following are the use cases where we need class loaders

1. Some of the classes in application are getting used for a finite period of time. By using custom class loaders, we can unload these classes after use. In this way it helps in better memory management.

2. Classes can be loaded from anywhere.
For example: Databases, Networks, or even the source can be defined on the fly.

Hiç yorum yok:

Yorum Gönder