English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Explicação Detalhada do Mecanismo de Carregamento de Classes no JAVA (Recomendado)

A compilação de código-fonte JAVA é composta por três processos:

1、Mecanismo de compilação de código-fonte

2、Mecanismo de carga de classes

3、Mecanismo de execução de classes

Aqui, introduzimos principalmente os dois mecanismos: compilação e carga de classes.

Um, compilação de código-fonte

A compilação de código é feita pelo compilador de código JAVA. Principalmente, compila o código-fonte em arquivo de bytecode (arquivo class). O formato do arquivo bytecode é dividido em duas partes principais: o pool de constantes e o bytecode de métodos.

Dois, carga de classes

A vida útil da classe começa com a carga para a memória do virtual machine e termina com a desativação da memória. O processo tem sete fases, e todas as fases antes da inicialização pertencem ao parte de carga da classe.

Carga----Verificação----Preparação----Análise-----Inicialização----Uso-----Desmemporação

O sistema pode carregar uma classe pela primeira vez quando usá-la, ou pode usar um mecanismo de pré-carga para carregar uma classe. Quando executar um programa java, será iniciado um processo de máquina virtual java, e os dois programas java executados duas vezes estarão em dois processos JVM diferentes, e os dois JVMs não compartilharão dados.

1、Fase de carga

A carga durante esse processo é uma fase do mecanismo de carga de classes, essas duas conceitos não devem ser confundidos, essa fase precisa concluir as seguintes tarefas:

1)Obtém o fluxo de bytes binário definindo essa classe por meio do nome completo da classe.

2)Transforma a estrutura de armazenamento estático representada por esse fluxo de bytes em uma estrutura de dados de tempo de execução no área de métodos.

3)Gera um objeto Class representando essa classe no java heap, servindo como entrada para acessar esses dados no área de métodos.

Devido ao fato de que o primeiro ponto não especifica de onde e como obter o fluxo de bytes binário da classe, esta área deixa muito espaço para os desenvolvedores. Isso será介绍的后面类加载器中。

2、准备阶段

这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。

1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。

2、这里设置的初始值,通常是指数据类型的零值。

private static int a = 3;
 这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。

3、初始化阶段

初始化是类加载机制的最后一步,这个时候才真正开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序。

java类中对类变量指定初始值有两种方式:1、声明类变量时指定初始值;2、使用静态初始化块为类变量指定初始值。

初始化的时机

1)创建类实例的时候,分别有:1、使用new关键字创建实例;2、通过反射创建实例;3、通过反序列化方式创建实例。

new Test();
Class.forName("com.mengdd.Test");

2)调用某个类的类方法(静态方法)

Test.doSomething();

3)访问某个类或接口的类变量,或为该类变量赋值。 

int b=Test.a;
Test.a=b;

4)初始化某个类的子类。当初始化子类的时候,该子类的所有父类都会被初始化。

5)直接使用java.exe命令来运行某个主类。

除了上面几种方式会自动初始化一个类,其他访问类的方式都称不会触发类的初始化,称为被动引用。

1、子类引用父类的静态变量,不会导致子类初始化。

public class SupClass
public static void main(String[] args)
 public static int a = 123;
 public static final String A= "MIGU";
 public static void main(String[] args)
  System.out.println("supclass init");
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);
public class SubClass extends SupClass
public static void main(String[] args)
 public static final String A= "MIGU";
 public static void main(String[] args)
  System.out.println("subclass init");
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);
public class Test
public static void main(String[] args)
 public class TestMain
 public static void main(String[] args)
  System.out.println(SubClass.a);
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);

}

supclass init
123

2、通过数组定义引用类,不会触发此类的初始化

public class SupClass
public static void main(String[] args)
 public static int a = 123;
 public static final String A= "MIGU";
 public static void main(String[] args)
  System.out.println("supclass init");
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);
public class Test
public static void main(String[] args)
 public class TestMain
 public static void main(String[] args)
  public class Test10SupClass[] spc = new SupClass[
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);

}

3];

ao referenciar constantes, não aciona a inicialização da classe
public static void main(String[] args)
 public class ConstClass
 public static final String A= "MIGU";
 public static void main(String[] args)
  static
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);
System.out.println("ConstCLass init");
public static void main(String[] args)
 public class TestMain
 public static void main(String[] args)
  {
 System.out.println(ConstClass.A);
System.out.println(ConstClass.A);

}

Resultados da execução:

MIGU

Quando se usa o final para modificar uma variável de classe, seu valor já está determinado no tempo de compilação e colocado no pool de constantes, então, ao acessar a variável da classe, é equivalente a obter diretamente do pool de constantes, sem inicializar a classe.

1Passos de inicialização

2Se a classe ainda não foi carregada e conectada, o programa carregará e conectará a classe primeiro.

3Se a classe pai direta da classe não foi carregada, inicialize primeiro a classe pai direta.

Se a classe tiver instruções de inicialização, o sistema executará essas instruções de inicialização uma a uma.

No segundo passo, se o pai direto novamente tiver pai direto, o sistema repetirá esses três passos novamente para inicializar esse pai, e assim por diante, o JVM inicializa sempre primeiro a classe java.lang.Object. Quando o programa usar qualquer classe ativamente, o sistema garante que a classe e todas as classes pai serão inicializadas.

Aqui está o mecanismo de carregamento de classes do JAVA que o editor lhe apresentou (recomendado), esperando que ajude a todos!3Declaração: O conteúdo deste artigo é extraído da Internet, pertence ao respectivo detentor dos direitos autorais, o conteúdo é contribuído e carregado voluntariamente pelos usuários da Internet, este site não possui direitos de propriedade, não foi editado manualmente e não assume responsabilidade legal relevante. Se você encontrar conteúdo suspeito de violação de direitos autorais, por favor, envie um e-mail para: notice#w

Você Também Gostaria de Ver