Java と他の言語の違いは、Java は Java 仮想マシン (JVM) 上で実行されることです。これは、コンパイルされたコードが、特定のマシンで実行される形式ではなく、プラットフォームに依存しない形式で保存されることを意味します。この形式には、従来の実行可能コード形式とは多くの重要な違いがあります。具体的には、C プログラムや C++ プログラムとは異なり、Java プログラムは独立した実行可能ファイルではなく、多数の個別のクラス ファイルで構成され、各クラス ファイルは Java クラスに対応します。 さらに、これらのクラス ファイルはすぐにはメモリにロードされませんが、プログラムが必要とするときにロードされます。 クラス ローダーは、Java 仮想マシンでクラスをメモリにロードするために使用されるツールです。さらに、Java クラス ローダーも Java で実装されています。この方法により、Java 仮想マシンについて深く理解していなくても、独自のクラス ローダーを簡単に作成できます。
なぜクラスローダーを作成するのでしょうか?
Java 仮想マシンにはすでにクラス ローダーがあるのですが、他のクラス ローダーを自分で作成する必要がありますか? 良い質問です。デフォルトのクラスローダーは、ローカルシステムからクラスをロードする方法のみを知っています。プログラムが完全にネイティブでコンパイルされている場合、通常はデフォルトのクラス ローダーが適切に機能します。しかし、Java の最も興味深い点の 1 つは、ローカルだけでなくネットワークからクラスをロードするのがいかに簡単であるかということです。
たとえば、ブラウザはカスタム クラス ローダーを通じてクラスをロードできます。 クラスをロードする方法もたくさんあります。 Java の最も興味深い点の 1 つは、単にローカルまたはネットワークからだけでなく、Java をカスタマイズできることです。
* 信頼できないコードを実行する前にデジタル署名を自動的に検証します
* ユーザーが提供したパスワードに基づいてコードを復号化します
* ユーザーのニーズに応じてクラスを動的に作成します。JDK (Java Software Development Kit) アプレットビューア (小規模アプリケーション ブラウザ) などを使用している場合は、カスタム クラス ローダーの例をバイトコードの形式でアプリケーションに簡単に統合できます。
Java 埋め込みブラウザの場合は、すでにカスタム クラス ローダーを使用しています。 Sun が最初に Java 言語をリリースしたとき、最も興奮したことの 1 つは、Java がリモート Web サイトからダウンロードしたコードをどのように実行するかを観察することでした。リモートサイトからHTTP経由で実行
P 接続によって送信されるバイトコードは少し奇妙に見えます。 Java にはカスタム クラス ローダーをインストールする機能があるため、これが機能します。アプレット ブラウザにはクラス ローダーが含まれています。このクラス ローダーはローカルで Java クラスを検索するのではなく、リモート サーバーにアクセスし、HTTP 経由で元のバイトコード ファイルをロードし、それを Java 仮想マシン内の Java クラスに変換します。もちろん、クラス ローダーは他にも多くのことを行います。安全でない Java クラスをブロックし、異なるページ上の異なるアプレットが相互に干渉しないようにします。 Luke Gorrie が作成したパッケージである Echidna は、複数の Java アプリケーションを Java 仮想マシンで安全に実行できるようにするオープン Java ソフトウェア パッケージです。カスタム クラス ローダーを使用して各アプリケーションにクラス ファイルのコピーを提供することで、アプリケーション間の干渉を防ぎます。
Javaクラスローダー:
Java にはデフォルトで、ブートストラップ クラス ローダー、拡張クラス ローダー、システム クラス ローダー (アプリケーション クラス ローダーとも呼ばれます) の 3 つのクラス ローダーがあります。
クラスローダーは、Java の最も強力な機能の 1 つです。しかし、開発者はコンポーネントのクラスロードを忘れることがよくあります。クラス ローダーは、実行時にクラス ファイルを検索してロードする役割を担うクラスです。 Java では、さまざまなクラス ローダー (カスタム クラス ローダーも含む) を使用できます。
Java プログラムには多数のクラス ファイルが含まれており、それぞれが 1 つの Java クラスに対応します。静的 C プログラムとは異なり、これらのクラス ファイルは一度メモリにロードされ、いつでもロードする必要があります。これがクラスローダーの違いです。ソース ファイル (通常は .class ファイルまたは .jar ファイル) からプラットフォームに依存しないバイトコードを取得し、それを JVM メモリ空間にロードして、解釈して実行できるようにします。デフォルトでは、アプリケーションの各クラスは java.lang.ClassLoader によってロードされます。継承できるため、自由に機能を拡張できます。
カスタムクラスローダー
java.io.* をインポートします。
java.net.* をインポートします。
java.util.* をインポートします。
java.lang.reflect.Methodをインポートします。
パブリック クラス CustomClassLoader extends URLClassLoader {
private FileInputStream input = null;
private ByteArrayOutputStream out = null; バイト配列出力ストリーム;
private String[] url = null; //クラスファイルのロードパス;
private byte[] data = null;
private String extensionalName = "" //クラスファイル拡張子;
public CustomClassLoader(URL[] urls) が例外をスローします{
スーパー(URL);
this.url = 新しい文字列[urls.length];
for (int i = 0; i < urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* URLを解析する
*/
private void setFilePath() {
for (int i = 0; i < this.url.length; i++) {
if (this.url[i].substring(0,4).toLowerCase().equals("file") == true) {
this.url[i] = this.url[i].substring(5);
}
}
}
/*
※指定したクラス名(パッケージ名+クラス名)のファイルのバイトコードを取得
* @name 名前文字列
* @戻りバイト[]
*/
private byte[] getFileData(文字列名) {
試す {
this.setFilePath();
for (文字列 URL : this.url) {
文字列ファイル名 = URL + name.replace('.', '/').concat(".") +
this.getExtensionalName();
input = 新しい FileInputStream(新しいファイル(ファイル名));
if (入力 != null) {
壊す;
}
}
out = 新しい ByteArrayOutputStream();
データ = 新しいバイト [1024];
int len = -1;
while ((len = input.read(data)) != -1) {
out.write(データ, 0, len);
}
データ = out.toByteArray();
} catch (例外 e) {
e.printStackTrace();
} ついに {
試す {
if (入力 != null)
input.close();
if (out != null)
out.close();
データを返す。
} catch (例外 e) {
e.printStackTrace();
null を返します。
}
}
}
/*
* 指定されたクラス名に基づいてクラスファイルを検索します
* @param 名前文字列
* @return クラス
*/
protected Class findClassByName(文字列名) {
試す {
byte[] データ = this.getFileData(name);
if (データ == null) {
null を返します。
}
return this.defineClass(name, data, 0, data.length);
} catch (例外 e) {
e.printStackTrace();
null を返します。
}
}
/*
*loadClass()メソッドをオーバーライドします
* @param 名前文字列
* @return クラス
*/
public ClassloadClass(文字列名) {
クラス c = null;
試す {
c = super.loadClass(名前);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} ついに {
if (c == null) //親クラスのデフォルトメソッドが指定されたクラスにロードされていない場合、カスタムメソッドを使用してそれを検索します
c = this.findClassByName(名前);
cを返します。
}
}
public String getExtensionalName() {
拡張名を返します。
}
public void setExtensionalName(String extensionalName) {
this.extensionalName = 拡張名;
}
public static void main(String[] args) throws Exception {
URL[] url = new URL[] {new URL("file:e:/")} //ロードするクラスへのパスを追加します。
//ネットワークでもローカルでも構いません
CustomClassLoader csl = 新しい CustomClassLoader(url);
csl.setExtensionalName("rs");
クラス c1 = csl.loadClass("com.demo");
オブジェクト obj = c1.newInstance();
メソッド method = c1.getMethod("printText", null);
メソッド.invoke(obj, null);
}