A diferença entre Java e outras linguagens é que Java roda na Java Virtual Machine (JVM). Isso significa que o código compilado é salvo em um formato independente de plataforma, em vez de um formato executado em uma máquina específica. Este formato tem muitas diferenças importantes em relação ao formato de código executável tradicional. Especificamente, diferentemente de um programa C ou C++, um programa Java não é um arquivo executável independente, mas consiste em muitos arquivos de classe separados, cada arquivo de classe correspondendo a uma classe Java. Além disso, esses arquivos de classe não são carregados na memória imediatamente, mas quando o programa precisa deles. Um carregador de classes é uma ferramenta usada na máquina virtual Java para carregar classes na memória. Além disso, o carregador de classes Java também é implementado em Java. Dessa forma, você pode criar facilmente seu próprio carregador de classes sem ter um conhecimento profundo da máquina virtual Java.
Por que criar um carregador de classes?
Agora que a máquina virtual Java já possui um carregador de classes, precisamos criar outros nós mesmos. Boa pergunta. O carregador de classes padrão só sabe como carregar classes do sistema local. Quando seu programa é compilado de forma totalmente nativa, o carregador de classes padrão geralmente funciona bem. Mas uma das coisas mais interessantes sobre Java é como é fácil carregar classes da rede em vez de apenas localmente.
Por exemplo, um navegador pode carregar classes por meio de um carregador de classes customizado. Existem também muitas maneiras de carregar classes. Uma das coisas mais interessantes sobre Java é que você pode personalizá-lo simplesmente no local ou na rede:
* Verifique automaticamente as assinaturas digitais antes de executar código não confiável
* Descriptografe o código com base na senha fornecida pelo usuário
* Crie classes dinamicamente de acordo com as necessidades do usuário. Qualquer coisa de seu interesse pode ser facilmente integrada ao seu aplicativo na forma de bytecode. Exemplos de carregadores de classes personalizados se você tiver usado o appletviewer JDK (Java Software Development Kit) (navegador de aplicativos pequenos) ou outro.
Para navegadores Java integrados, você já usa um carregador de classes customizado. Quando a Sun lançou pela primeira vez a linguagem Java, uma das coisas mais interessantes foi observar como o Java executava código baixado de um site remoto. Executar a partir de site remoto via HTTP
O bytecode transmitido pela conexão P parece um pouco estranho. Isso funciona porque Java tem a capacidade de instalar carregadores de classes customizados. O navegador de miniaplicativos contém um carregador de classes. Este carregador de classes não localiza classes Java localmente. Em vez disso, ele acessa o servidor remoto, carrega o arquivo de bytecode original por meio de HTTP e o converte em uma classe Java na máquina virtual Java. É claro que os carregadores de classes fazem muitas outras coisas: eles bloqueiam classes Java inseguras e evitam que diferentes miniaplicativos em páginas diferentes interfiram uns nos outros. Echidna, um pacote escrito por Luke Gorrie, é um pacote de software Java aberto que permite que vários aplicativos Java sejam executados com segurança em uma máquina virtual Java. Ele evita interferência entre aplicativos usando um carregador de classes personalizado para fornecer a cada aplicativo uma cópia do arquivo de classe.
carregador de classes java:
Existem três carregadores de classes por padrão em Java: carregador de classes bootstrap, carregador de classes de extensão e carregador de classes do sistema (também chamado de carregador de classes de aplicativo)
Os carregadores de classes são um dos recursos mais poderosos do Java. Mas os desenvolvedores muitas vezes se esquecem de carregar os componentes em classe. Um carregador de classes é uma classe responsável por localizar e carregar arquivos de classe em tempo de execução. Java permite o uso de diferentes carregadores de classes, até mesmo carregadores de classes customizados.
Os programas Java contêm muitos arquivos de classe, cada um correspondendo a uma única classe Java. Ao contrário dos programas C estáticos, esses arquivos de classe são carregados na memória uma vez e precisam ser carregados a qualquer momento. Isso é o que torna os carregadores de classes diferentes. Ele obtém bytecodes independentes de plataforma de arquivos de origem (geralmente arquivos .class ou .jar) e depois os carrega no espaço de memória da JVM para que possam ser interpretados e executados. Por padrão, cada classe de um aplicativo é carregada por java.lang.ClassLoader. Como pode ser herdado, sua funcionalidade pode ser aprimorada livremente.
Carregador de classes personalizado
importar java.io.*;
importar java.net.*;
importar java.util.*;
importar java.lang.reflect.Method;
classe pública CustomClassLoader estende URLClassLoader {
private FileInputStream input = null; //Fluxo de entrada do arquivo
private ByteArrayOutputStream out = null; //fluxo de saída da matriz de bytes
private String[] url = null; //Caminho de carregamento do arquivo de classe
private byte[] data = null; //bytecode do arquivo de classe
private String extensionalName = ""; //Extensão do arquivo de classe
public CustomClassLoader(URL[] urls) lança exceção{
super(URL);
this.url = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* Analisar URL
*/
private void setFilePath() {
for (int i = 0; i < this.url.length; i++) {
if (this.url[i].substring(0,4).toLowerCase().equals("arquivo") == verdadeiro) {
esta.url[i] = esta.url[i].substring(5);
}
}
}
/*
* Obtenha o bytecode do arquivo com o nome da classe especificado (nome do pacote + nome da classe)
* @nome nome String
* @return byte[]
*/
byte privado[] getFileData(Nome da string) {
tentar {
this.setFilePath();
for (URL da string: this.url) {
String nomeArquivo = url + nome.replace('.', '/').concat(".") +
this.getExtensionName();
input = new FileInputStream(new Arquivo(nomeArquivo));
if (entrada! = nulo) {
quebrar;
}
}
saída = new ByteArrayOutputStream();
dados = novo byte[1024];
int len = -1;
while ((len = input.read(dados)) != -1) {
out.write(dados, 0, len);
}
dados = out.toByteArray();
} catch (Exceção e) {
e.printStackTrace();
} finalmente {
tentar {
if (entrada! = nulo)
input.close();
if (fora! = nulo)
out.close();
retornar dados;
} catch (Exceção e) {
e.printStackTrace();
retornar nulo;
}
}
}
/*
* Pesquise arquivos de classe com base no nome da classe especificado
* @param nome String
* @return Aula
*/
classe protegida findClassByName (nome da string) {
tentar {
byte[] dados = this.getFileData(nome);
if (dados == nulo) {
retornar nulo;
}
retornar this.defineClass (nome, dados, 0, data.length);
} catch (Exceção e) {
e.printStackTrace();
retornar nulo;
}
}
/*
* Substituir método loadClass()
* @param nome String
* @return Aula
*/
Classe pública loadClass(Nome da string) {
Classe c = nulo;
tentar {
c = super.loadClass(nome);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finalmente {
if (c == null) //Quando o método padrão da classe pai não é carregado na classe especificada, use um método personalizado para encontrá-lo
c = this.findClassByName(nome);
retornar c;
}
}
public String getExtensionName() {
return extensionNome;
}
public void setExtensionalName(String extensionalName) {
this.extensionName = extensionalName;
}
public static void main(String[] args) lança exceção {
URL[] url = new URL[] {new URL("file:e:/")} //Adicione o caminho para a classe que deseja carregar
//Pode ser de rede ou local
CustomClassLoader csl = new CustomClassLoader(url);
csl.setExtensionalName("rs");
Classe c1 = csl.loadClass("com.demo");
Objeto obj = c1.newInstance();
Método método = c1.getMethod("printText", null);
método.invoke(obj, null);
}