Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Запуск компилятора, изнутри Java программы 
:(
    Опции темы
simanyay
Дата 30.6.2005, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



Код

public boolean compile(String source) {
    try {
        Process proc = Runtime.getRuntime().exec(compiler + " " + flags + " " + source);
        BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = null;
            
        if(!in.ready()) return true;
            
        while((line = in.readLine()) != null) {
            // TODO: getLastError()?
        }
            
        proc.destroy();
    } catch(Exception ex) {
        return false;
    }
        
    return false;
}


т.е., насколько вы уже поняли, мне необходимо скомпилировать некий .java файл. Полный путь до компилятора, в виде c:/jdk/bin/javac.exe лежит в переменной compiler, флаги компиляции в flags и полный путь до сурца (в том же виде) в source.
Все переменные существуют и не равны null.
При этом метод возвращает true, если компиляция прошла успешно, т.е. javac не выдал на консоль ничего. В случае исключительной ситуации или ошибки в исходнике возвращается false.
А ещё необходима мультиплатформенность. В зависимости от системы уже прибавляется .exe, но мне кажется, что могут быть заморочки с \\ и /. Я использую /.
Проблема заключается в том, что ничего не компилируется.

P.S. На TODO внимания не обращайте.

Заранее спасибо.
Пойду поем.


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
tux
Дата 1.7.2005, 03:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Летатель
***


Профиль
Группа: Участник Клуба
Сообщений: 1853
Регистрация: 10.2.2005
Где: msk.ru

Репутация: 31
Всего: 132



У меня все работает в таком виде. Slackware Linux 10.1, JDK 1.4.2_08. Даже не представляю в чем может быть проблема, хотя в Windows не проверял, может быть там не все так гладко. Альтернативный способ откомпилить классы:
Код

public int compile(String source) {
    com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
    String[] args = new String[] { source };

    int status = javac.compile(args);
    return status;
}

Класс com.sun.tools.javac.Main находится в jdk.home/lib/tools.jar.
PM MAIL Skype GTalk Jabber YIM   Вверх
simanyay
Дата 1.7.2005, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



tux, спасибо, если с тем ничего не выйдет, попробую. Мне, просто, ещё и другие компиляторы других языков поддерживать нужно будет (C#, C, etc.).


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
Domestic Cat
Дата 1.7.2005, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(simanyay @ 30.6.2005, 11:41)
с \\ и /. Я использую /.

Код

System.getProperty("file.separator");





--------------------

PM   Вверх
simanyay
Дата 1.7.2005, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



Цитата(Domestic @ 1.7.2005, 12:34)
System.getProperty("file.separator");


Опаньки, спасибки.


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
simanyay
Дата 1.7.2005, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



В связи с тем, что вот такой код
Код

Process p = Runtime.getRuntime().exec("\"C:\\WINDOWS\\notepad.exe\"");
p.waitFor();

работает, смею предположить, что не работает
Код

proc.getInputStream()


Ни у кого никаких мыслей нет?


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
simanyay
Дата 1.7.2005, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



После курсов вождения я смело запускаю все программы, кроме Sunовских. Почему-то и javac, java и другие запускаются (т.е. процесс в памяти висит) и... не останавливаются. Так и остаются висеть smile


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
Domestic Cat
Дата 1.7.2005, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(simanyay @ 1.7.2005, 09:21)
После курсов вождения я смело запускаю все программы, кроме Sunовских. Почему-то и javac, java и другие запускаются (т.е. процесс в памяти висит) и... не останавливаются. Так и остаются висеть smile

Может, переставить СДК?


Цитата(simanyay @ 1.7.2005, 04:26)

Ни у кого никаких мыслей нет?

Попробуй примеры отсюда
http://java.sun.com/developer/JDCTechTips/2003/tt0304.html
- будут работать?


--------------------

PM   Вверх
simanyay
Дата 1.7.2005, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



Цитата(Domestic @ 1.7.2005, 20:44)
Может, переставить СДК?


Так с консольки (cmd) они работают.

Цитата(Domestic @ 1.7.2005, 20:44)
Попробуй примеры отсюда


После того, как я поменял ls на cmd /c заработали. Но когда я попытался javac запустить через cmd /c:
Цитата
CreateProcess: "cmd /c C:\Program Files\Java\jdk1.5.0\bin\javac.exe" error=2

Добавлено @ 19:37
(поговорив по телефону)

Кстати, насколько я помню, error=2 это когда не найдена программа


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
Domestic Cat
Дата 1.7.2005, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(simanyay @ 1.7.2005, 10:27)
CreateProcess: "cmd /c C:\Program Files\Java\jdk1.5.0\bin\javac.exe" error=2

Это в винде означает File Not Found Error, то есть javacу ты не дал никакого файла компилить smile smile smile
Т. е. это означает что все работает.

Можно проще
Код

            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec("javac");
            InputStream stderr = proc.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ( (line = br.readLine()) != null)
                System.out.println(line);
            int exitVal = proc.waitFor();



--------------------

PM   Вверх
simanyay
Дата 1.7.2005, 23:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



Сделал.
Короче, поговорив сначала с Котом в аське, а потом с котом васькой я решил взглянуть на эту проблему по другому. Опишу (вдруг кому ещё такая фигня попадется):
Моей целью было написать класс, который компилировал бы представляемые .java файлы. Так как в разных системах javac располагается в разных местах, сл-но я хотел прописывать полный путь, который хранился бы в конфиге. Но тут возникла проблема, которую я так и не смог решить. Почему-то .exec(...) упорно отказывается запускать такого вида строку:

cmd /c c:\\Program Files\\Java\\jdk1.5.0\\bin\\javac.exe e:\\dev\\java\\jizer-data\\java_src\\Hello.java

Причём я пробовал и в кавычки брать - всё равно не работал. Ошибка была интересная

'C:\Program' is not recognized as an internal or external command,
operable program or batch file.


Кстати, попробуйте запустить эту строку (с кавычками и без) в start > run. Тоже не получится.
(Hint: чтобы видеть результы надо поменять флаг /c на /k)

Но если я запускал не через полный путь, т.е. просто javac ..., то всё работало. Сл-но я решил, что просто буду динамически управлять переменной окружения PATH.

Всем спасибо за помощь, а Коту + в репу


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
simanyay
Дата 2.7.2005, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Антон Ковалёв
****


Профиль
Группа: Участник
Сообщений: 2053
Регистрация: 22.8.2002

Репутация: 3
Всего: 36



Нашёл альтернативный способ запуска программ из Java.

Предисловие:
В стандартном способе запуска программ, есть проблема, которая в официальной документации описывается так:
Цитата
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

Что в переводе означает
Цитата
Поскольку некоторые нативные платформы обеспечивают ограниченный размер буфера для потоков стандартного ввода и вывода, неспособность сразу написать в поток ввода или прочитать поток вывода у дочернего процесса, может вызвать его блокировку или даже застой.


Решение нашёл на JavaWorld (When Runtime.exec() won't) и немного переписал класс под себя. В зависимости от ситуации, удобно пользоваться и тем и другим, поскольку в большей части они похожи:
Код

package org.simanyay.jizer.kernel;

import java.util.*;
import java.io.*;

public class Executer {
    private List<String> err_output; // Error output
    private List<String> nor_output; // Normal output
    private int exit_value;
    
    private final int ARRAY = 1;
    private final int STRING = 2;
    
    public void execute(String cmd) throws Exception {
        genericExec(cmd, STRING);
    }
    
    public void execute(String[] cmd) throws Exception {
        genericExec(cmd, ARRAY);
    }
    
    private void genericExec(Object cmd, int type) throws Exception {
        Runtime runtime = Runtime.getRuntime();
        Process proc = null;
        
        if(type == STRING) {
            proc = runtime.exec((String) cmd);
        } else if(type == ARRAY) {
            proc = runtime.exec((String[]) cmd);
        } else throw new IllegalArgumentException();
        
        Streamer err_stream = new Streamer(proc.getErrorStream());
        Streamer out_stream = new Streamer(proc.getInputStream());
        
        err_stream.run();
        out_stream.run();
        
        exit_value = proc.waitFor();
    }

    public int getExitValue() {
        return exit_value;
    }
}

// Я выкинул из этого класса явное указание типа 
// вывода (stdout или же stderr) поскольку в моей задаче это не требовалось.
// Добавить обратно труда не составит, тем более, что это есть в той статье
class Streamer extends Thread {
    private InputStream input;

    public Streamer(InputStream in) {
        input = in;
    }
    
    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            String line = null;
            
            while((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }
}


Засим моя проблема запуска компилятора решена полностью. Благодарю за внимание.

P.S. Думаю, неплохо было бы это как дополнение к статье Антона Сабурова про вызов внешних программ, которая в ФАКе, добавить.


--------------------
«It's better to be a pirate than to join the Navy» — Steve Jobs.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0632 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.