Действительно ли возможно “добавить” к пути к классу динамично в Java?

23
задан om-nom-nom 1 July 2013 в 08:46
поделиться

5 ответов

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

общедоступный класс URLClassLoader расширяет SecureClassLoader

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

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

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

С тех пор: 1.2

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

/**
 * 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;
        }
    }
22
ответ дан Lawrence Dol 29 November 2019 в 02:58
поделиться

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

1
ответ дан Jim Barrows 29 November 2019 в 02:58
поделиться

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

попытка

java -cp *.jar:. myClass

или

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

или

java -jar file.jar
0
ответ дан Milhous 29 November 2019 в 02:58
поделиться

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

путь к классу набора = % пути к классу %;../классы;../сотрясает /* java ParserTester

В Unix, экспортируйте путь к классу = путь к классу % %:../classes:../сотрясает /* java ParserTester

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

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

, При попытке генерировать файл Java динамично, скомпилируйте и добавьте в путь к классу, установите каталог, в который файл класса сгенерирован в пути к классу заранее. Это должно загрузить класс. При изменении уже сгенерированного класса Java в основном перекомпилировав после модификации и если Вы хотите загрузить новый класс, необходимо использовать пользовательский загрузчик класса для предотвращения кэширования класса.

0
ответ дан raffimd 29 November 2019 в 02:58
поделиться

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

java parserTester

вместо

Java - путь к классу../классы;../сотрясать;. parserTester

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

  • Запуск класс
  • От основного метода lauch другой класс программно набор путь к классу там.
  • Конец истории.

Что-то как следующий "Java - псевдо код"

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

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

-1
ответ дан OscarRyz 29 November 2019 в 02:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: