1. Um comando corresponde a um processo.
Quando iniciamos um programa Java, ou seja, quando iniciamos um método principal, um processo de máquina virtual Java será iniciado, por mais complexo que seja o processo. Diferentes processos JVM não afetarão uns aos outros. É por isso que se diz que o programa Java possui apenas uma entrada – o método principal, que é chamado pela máquina virtual. Os dois métodos principais correspondem a dois processos JVM, iniciando dois carregadores de classes diferentes e, na verdade, operando classes diferentes. Portanto, eles não afetarão um ao outro.
2. Carregamento de classe.
Quando usamos uma classe, se a classe não tiver sido carregada na memória, o sistema irá inicializar a classe por meio de carregamento, conexão e inicialização.
1. Carregamento de classe: refere-se à leitura do arquivo de classe da classe na JVM e à criação de um objeto Class para ele.
2. Conexão de classe: refere-se à fusão dos dados binários da classe no JRE, que é dividido em três etapas:
a) Verificação: Verifique a exatidão dos dados do arquivo de classe carregado.
b) Preparação: Aloque espaço de armazenamento para as variáveis estáticas da classe e execute a inicialização padrão.
c). Análise: Substitua as referências de símbolos nos dados binários da classe por referências diretas.
3. Inicialização: Inicialize as variáveis estáticas e os blocos de inicialização estáticos da classe.
(Nota: Para uma propriedade estática do tipo final, se o valor da propriedade tiver sido obtido em tempo de compilação, chamar a propriedade não fará com que a classe seja inicializada, pois isso equivale a usar uma constante;
Usar o método ClassLoader() apenas carrega a classe e não a inicializa. )
3. Carregador de classes.
O carregador de classes é responsável por carregar os arquivos .class na memória e gerar os objetos java.lang.Class correspondentes. Ele é responsável por carregar todas as classes. Uma vez que uma classe é carregada na JVM, ela não será carregada novamente.
Em Java, uma classe é identificada por seu nome de classe totalmente qualificado (ou seja, nome do pacote + nome da classe).
Na JVM, uma classe é identificada por seu nome de classe totalmente qualificado e seu carregador de classes.
Quando a JVM estiver em execução, três ClassLoaders serão gerados, a saber: BootstrapClassLoader (carregador de classes raiz), ExtClassLoader (carregador de classes estendido) e AppClassLoader (carregador de classes do sistema). A estrutura UML é a seguinte:
Entre eles, BootstrapClassLoader é responsável por carregar a biblioteca de classes principal do JRE. Não é uma subclasse do ClassLoader e é escrito em C++, portanto, não podemos vê-lo em Java. Quando obtido através do método getParent() de sua subclasse, null será. ser devolvido. BootstrapClassLoader é responsável por carregar bibliotecas de classes principais Java, como rt.jar e charsets.jar no destino JRE.
Como pode ser visto na figura, ExtClassLoader e AppClassLoader são subclasses de ClassLoader. Você não pode vê-los na API, eles estão no arquivo rt.jar. Os nomes de classe totalmente qualificados são:
sun.misc.Launcher$ExtClassLoader e sun.misc.Launcher$AppClassLoader.
Entre eles, ExtClassLoader é responsável por carregar o pacote JAR no diretório de extensão JRE ext, e AppClassLoader é responsável por carregar o pacote de classe no caminho Classpath.
O teste é o seguinte:
Copie o código do código da seguinte forma:
pacote com.stopTalking.crazy;
classe pública TestClassLoader {
public static void main(String[] args) {
//Obtém o carregador de classes do thread atual
Carregador ClassLoader = Thread.currentThread().getContextClassLoader();
//Obtém o carregador de classes da classe System
ClassLoader loader1 = System.class.getClassLoader();
//Obtém o carregador de classe loader2 desta classe TestClassLoader
ClassLoader loader2 = TestClassLoader.class.getClassLoader();
//Obtém a classe pai do loader2
ClassLoader loader3 = loader2.getParent();
//Obtém a classe pai da classe pai do loader2
ClassLoader loader4 = loader3.getParent();
System.out.println(carregador);
System.out.println(carregador1);
System.out.println(loader2);
System.out.println(loader3);
System.out.println(loader4);
}
}
Saída do console:
Copie o código do código da seguinte forma:
//O carregador de classes obtido pela classe de thread atual é AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
//A classe System é carregada pelo carregador root e não pode ser acessada em java, portanto é nula
nulo
//O carregador de classe desta classe também é AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
nulo