Подтвердить что ты не робот

Можно ли "динамически добавлять" путь к классу в java?

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

Как я могу получить функциональность в вышеуказанной команде программно? Например, можно ли запустить:

java parserTester

и получить тот же результат? Я попытался использовать URLClassLoader, но он изменяет путь к классам и не добавляет к нему.

Thanx!


Спасибо за ответ Милхоус. Но это то, что я пытаюсь сделать. Как можно сначала получить банку в classpath? Я также попытался использовать собственный загрузчик классов: (

Это работает. Но жаль, что мне нужно запустить его только как: java parserTester Я хотел бы знать, возможно ли такое возможно?

Это должно быть так bcoz, у меня есть parserTester.java и .class в отдельной папке. Мне нужно сохранить структуру файла. В parserTester используется банка в отдельной папке jar.

4b9b3361

Ответ 1

Вы можете использовать java.net.URLClassLoader для загрузки классов с любым программным списком URL, который вы хотите:

открытый класс URLClassLoader расширяет SecureClassLoader

Этот загрузчик классов используется для загрузки классов и ресурсов из поиска путь URL-адресов, относящихся как к JAR файлов и каталогов. Любой URL-адрес, который заканчивается символом '/', считается ссылкой на каталог. В противном случае URL-адрес предполагается, что он относится к файлу JAR, который будет открываться по мере необходимости.

AccessControlContext потока который создал экземпляр URLClassLoader будет использоваться, когда впоследствии загрузка классов и ресурсы.

Загружаемые классы: по умолчанию разрешено только доступа к URL-адресам, указанным, когда Создан URLClassLoader.

С:     1.2

И небольшая причудливая работа может расширить его, чтобы поддерживать использование подстановочных путей, чтобы собрать все каталоги JAR (этот код имеет некоторые ссылки на утилиты, но их реализация должна быть очевидной в контексте):

/**
 * Add classPath to this loader 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 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;
        }
    }

Ответ 2

Вы можете реализовать собственный загрузчик классов, но этот класс /jar должен находиться в пути к классам для его выполнения.

попробовать

java -cp *.jar:. myClass

или

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

или

java -jar file.jar

Ответ 3

Я должен согласиться с двумя другими плакатами, похоже, что вы перегружаете тестовый класс. Это не так уж необычно иметь файлы .java и .class в отдельных папках, в то время как в зависимости от файлов jar еще в третьей, без программного изменения пути к классам. Если вы это делаете, потому что вы не хотите каждый раз вводить путь к классам в командной строке, я бы предложил оболочку script или командный файл. Еще лучше, IDE. Вопрос, который у меня действительно есть, - почему вы пытаетесь управлять classpath в коде?

Ответ 4

Я правильно понял? Единственная причина, по которой вы хотите запустить свой класс, не указав путь к классам и загрузив его во время выполнения?...

java parserTester

вместо

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

Возможно, я не понял вашу причину. Но если "это" то, что вы хотите, вы можете сделать следующее (хотя это не имеет большого значения для меня)

  • Запустите класс
  • Из основного метода lauch другого класса программно задается путь к нему.
  • Конец истории.

Что-то вроде следующего "java -pseudo code"

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

Скажите, пожалуйста, правильно ли. Если вы хотите сделать что-то еще, я с удовольствием помогу.

Ответ 5

Вы можете написать пакетный файл или файл оболочки script, чтобы экспортировать путь к классам и запустить java-программу. В Windows

установить classpath =% classpath%;../classes;../jars/* java ParserTester

В Unix, export classpath =% classpath%:../classes:../jars/* java ParserTester

Если вы назовете имя файла как parser.bat или parser.sh, вы можете просто запустить его, вызвав парсер в соответствующей ОС.

Из java 1.6 вы можете включить все банки в каталог в путь к классам, просто сказав /*

Если вы пытаетесь генерировать java файл динамически, компилируйте и добавьте в путь к классам, установите каталог, в который файл класса будет сгенерирован в пути к классам заранее. Он должен загрузить класс. Если вы изменяете уже сгенерированный класс java, в основном перекомпилируете после изменения, и если вы хотите загрузить новый класс, вам нужно использовать свой пользовательский загрузчик классов, чтобы избежать кэширования класса.

Ответ 6

Я думаю, что вы хотите, это "Обертка исполнения" или специфическая для платформы "Launcher"... Обычно этот компонент используется для обнаружения вашей ОС и архитектуры и зависимостей, а затем выполняет настройки перед запуском приложения. Это старый образец дизайна школы (разговор 80 и ранее), но он все еще используется много сегодня. Идея заключается в том, что программа может быть агностикой системы и среды, а пусковая установка будет готовить и сообщать программному обеспечению все, что ему нужно знать. Многие современные программы с открытым исходным кодом делают это с помощью сценариев оболочки и пакетных файлов и т.д.... например Apache Tomcat. Вы можете так же легко сделать оболочку в java и запустить ее с помощью командной строки exec (обязательно добавьте "&" до конца команды exec в * NIX, чтобы ваша оболочка могла выйти, оставив только ваше программное обеспечение... также позволяет закрыть окно оболочки, не убивая процесс)

Ответ 7

Отличная хорошая должность, в моем случае я сделал это, чтобы хорошо работать (примечание: Windows специфический):

set classpath=%classpath%;../lib/*
java -cp %classpath% com.test.MyClass