23
java -classpath ../classes;../jar;. parserTester

上記のコマンドの機能をプログラムで取得するにはどうすればよいですか? 同様に、次のように実行することは可能ですか:

java parserTester

同じ結果が得られますか?URLClassLoader を使用してみましたが、クラスパスが変更され、追加されません。

ありがとう!


Milhouさん、返信ありがとうございます。しかし、それが私がやろうとしていることです.最初にjarをクラスパスに入れるにはどうすればよいですか? 私もカスタムクラスローダーを使ってみました:(

それはうまくいきます..しかし、私はそれを次のように実行する必要があることを残念に思います: java parserTester 私はそのようなことが可能かどうか知りたいですか?

それはそうする必要があるので、私は parserTester.java と .class を別のフォルダーに持っています。ファイル構造を保持する必要があります。parserTester は、別の jar フォルダー内の jar を使用します。

4

7 に答える 7

22

java.net.URLClassLoader を使用して、任意のプログラムで定義された URL のリストを含むクラスをロードできます。

public class URLClassLoader は SecureClassLoader を拡張します

このクラスローダーは、JAR ファイルとディレクトリの両方を参照する URL の検索パスからクラスとリソースをロードするために使用されます。「/」で終わるすべての URL は、ディレクトリを参照していると見なされます。それ以外の場合、URL は、必要に応じて開かれる JAR ファイルを参照していると見なされます。

URLClassLoader のインスタンスを作成したスレッドの AccessControlContext は、その後クラスとリソースをロードするときに使用されます。

ロードされるクラスには、デフォルトで、URLClassLoader の作成時に指定された URL へのアクセスのみが許可されます。

以降: 1.2

そして、ちょっと派手なフットワークで、ワイルドカードを使用したパス名を使用して JAR のディレクトリ全体を取得できるように拡張できます (このコードにはユーティリティ メソッドへの参照がいくつかありますが、その実装はコンテキスト内で明らかなはずです)。

/**
 * Add classPath to this loader's classpath.
 * <p>
 * The classpath may contain elements that include a generic file base name.  A generic basename
 * is a filename without the extension that may begin and/or end with an asterisk.  Use of the
 * asterisk denotes a partial match. Any files with an extension of ".jar" whose base name match
 * the specified basename will be added to this class loaders classpath.  The case of the filename is ignored.
 * For example "/somedir/*abc" means all files in somedir that end with "abc.jar", "/somedir/abc*"
 * means all files that start with "abc" and end with ".jar", and "/somedir/*abc*" means all files
 * that contain "abc" and end with ".jar".
 *
 */
public void addClassPath(String cp) {
    String                              seps=File.pathSeparator;                // separators

    if(!File.pathSeparator.equals(";")) { seps+=";"; }                          // want to accept both system separator and ';'
    for(StringTokenizer st=new StringTokenizer(cp,seps,false); st.hasMoreTokens(); ) {
        String pe=st.nextToken();
        File   fe;
        String bn=null;

        if(pe.length()==0) { continue; }

        fe=new File(pe);
        if(fe.getName().indexOf('*')!=-1) {
            bn=fe.getName();
            fe=fe.getParentFile();
            }

        if(!fe.isAbsolute() && pe.charAt(0)!='/' && pe.charAt(0)!='\\') { fe=new File(rootPath,fe.getPath()); }
        try { fe=fe.getCanonicalFile(); }
        catch(IOException thr) {
            log.diagln("Skipping non-existent classpath element '"+fe+"' ("+thr+").");
            continue;
            }
        if(!GenUtil.isBlank(bn)) {
            fe=new File(fe,bn);
            }
        if(classPathElements.contains(fe.getPath())) {
            log.diagln("Skipping duplicate classpath element '"+fe+"'.");
            continue;
            }
        else {
            classPathElements.add(fe.getPath());
            }

        if(!GenUtil.isBlank(bn)) {
            addJars(fe.getParentFile(),bn);
            }
        else if(!fe.exists()) {                                                 // s/never be due getCanonicalFile() above
            log.diagln("Could not find classpath element '"+fe+"'");
            }
        else if(fe.isDirectory()) {
            addURL(createUrl(fe));
            }
        else if(fe.getName().toLowerCase().endsWith(".zip") || fe.getName().toLowerCase().endsWith(".jar")) {
            addURL(createUrl(fe));
            }
        else {
            log.diagln("ClassPath element '"+fe+"' is not an existing directory and is not a file ending with '.zip' or '.jar'");
            }
        }
    log.diagln("Class loader is using classpath: \""+classPath+"\".");
    }

/**
 * Adds a set of JAR files using a generic base name to this loader's classpath.  See @link:addClassPath(String) for
 * details of the generic base name.
 */
public void addJars(File dir, String nam) {
    String[]                            jars;                                   // matching jar files

    if(nam.endsWith(".jar")) { nam=nam.substring(0,(nam.length()-4)); }

    if(!dir.exists()) {
        log.diagln("Could not find directory for Class Path element '"+dir+File.separator+nam+".jar'");
        return;
        }
    if(!dir.canRead()) {
        log.error("Could not read directory for Class Path element '"+dir+File.separator+nam+".jar'");
        return;
        }

    FileSelector fs=new FileSelector(true).add("BaseName","EG",nam,true).add("Name","EW",".jar",true);
    if((jars=dir.list(fs))==null) {
        log.error("Error accessing directory for Class Path element '"+dir+File.separator+nam+".jar'");
        }
    else if(jars.length==0) {
        log.diagln("No JAR files match specification '"+new File(dir,nam)+".jar'");
        }
    else {
        log.diagln("Adding files matching specification '"+dir+File.separator+nam+".jar'");
        Arrays.sort(jars,String.CASE_INSENSITIVE_ORDER);
        for(int xa=0; xa<jars.length; xa++) { addURL(createUrl(new File(dir,jars[xa]))); }
        }
    }

private URL createUrl(File fe) {
    try {
        URL url=fe.toURI().toURL();
        log.diagln("Added URL: '"+url.toString()+"'");
        if(classPath.length()>0) { classPath+=File.pathSeparator; }
        this.classPath+=fe.getPath();
        return url;
        }
    catch(MalformedURLException thr) {
        log.diagln("Classpath element '"+fe+"' could not be used to create a valid file system URL");
        return null;
        }
    }
于 2008-12-31T08:55:51.697 に答える
1

他の 2 つのポスターに同意する必要があります。テスト クラスを複雑にしすぎているようです。プログラムでクラスパスを変更せずに、.java ファイルと .class ファイルを別々のフォルダーに置き、さらに 3 分の 1 の jar ファイルに依存することは、それほど珍しいことではありません。毎回コマンド ラインでクラスパスを入力する必要がないために実行している場合は、シェル スクリプトまたはバッチ ファイルをお勧めします。さらによいのは、IDE です。私が本当に持っている質問は、なぜコードでクラスパスを管理しようとしているのですか?

于 2008-12-31T06:32:17.197 に答える
0

独自のクラス ローダーを実装することもできますが、そのクラス/jar を実行するにはクラスパスに存在する必要があります。

試す

java -cp *.jar:. myClass

また

export CLASSPATH=./lib/tool.jar:.
java myClass

また

java -jar file.jar
于 2008-12-31T04:56:05.643 に答える
0

バッチ ファイルまたはシェル スクリプト ファイルを記述して、クラスパスをエクスポートし、Java プログラムを実行できます。Windows では、

set classpath=%classpath%;../classes;../jars/* Java ParserTester

Unix では、export classpath=%classpath%:../classes:../jars/* java ParserTester

ファイル名に parser.bat または parser.sh という名前を付けると、それぞれの OS で parser を呼び出すだけで実行できます。

Java 1.6 から、/* と言うだけで、ディレクトリ内のすべての jar をクラスパスに含めることができます。

javaファイルを動的に生成する場合は、コンパイルしてクラスパスに追加し、あらかじめクラスファイルを生成するディレクトリをクラスパスに設定してください。クラスをロードする必要があります。既に生成された Java クラスを変更する場合、基本的には変更後に再コンパイルし、新しいクラスをロードする場合は、カスタム クラス ローダーを使用してクラスのキャッシュを回避する必要があります。

于 2008-12-31T07:21:34.680 に答える
0

「実行ラッパー」またはプラットフォーム固有の「ランチャー」が必要だと思います...通常、このコンポーネントは、OS、アーキテクチャ、および依存関係を検出し、アプリケーションを起動する前に調整を行うために使用されます。古い学校のデザイン パターン (80 年代以前の話) ですが、今日でも多く使用されています。プログラムはシステムや環境にとらわれず、ランチャーは準備を行い、ソフトウェアが知る必要があるすべてのことを伝えるという考え方です。多くの最新のオープン ソース プログラムは、シェル スクリプトやバッチ ファイルなどを使用してこれを行います。たとえば、Apache Tomcat です。Java でラッパーを簡単に作成し、コマンド ライン exec でソフトウェアを起動することもできます (*NIX の exec コマンドの最後に「&」を追加して、ソフトウェアのみを実行したままラッパーを終了できるようにしてください。 . . プロセスを強制終了せずにシェル ウィンドウを閉じることもできます)。

于 2011-06-27T13:43:28.530 に答える
-1

分かりましたか?!クラスパスを指定せずにクラスを起動して実行時にロードしたいという唯一の理由はありますか?..。

java parserTester

それ以外の

java -classpath../classes;../jar;。parserTester

おそらく私はあなたの理由を理解できませんでした。しかし、「それが」あなたが望むのであれば、あなたは次のことをすることができます(それは私にはあまり意味がありませんが)

  • クラスを起動します
  • メインメソッドから別のクラスをプログラムで設定し、そこにクラスパスを設定します。
  • 歴史の終わり。

次の「java-pseudocode」のようなもの

public static void main( String [] args ) {
    String classpath = "classes;../jar";
    Runtime.getRuntime().execute("java + classpath + " parserTester ");
}

正しければ教えてください。あなたが何か他のことをしたいのなら、私は喜んで助けます。

于 2008-12-31T06:17:37.463 に答える
-2

私の場合、うまくいくようにこれを行いました(注:Windows固有):

set classpath=%classpath%;../lib/*
java -cp %classpath% com.test.MyClass 
于 2011-03-31T15:53:35.747 に答える