Runtime.exec зависает при вызове ant-скрипта, содержащего задачу hbm2ddl? - PullRequest
6 голосов
/ 16 августа 2011

Для запуска ant-скрипта я использую метод exec класса java.lang.Runtime следующим образом:

Process process = Runtime.getRuntime ().Exec (JAVA_HOME ANT_HOME -jar / lib / ant-launcher.jar-BuildFile file.xml);

Этот метод, несмотря на его кажущуюся простоту, но создает несколько проблем и описывается в javadoc какследует:

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

Чтобы решить эту проблему, я сослался на следующую статью: http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1 Этот метод работал для бездомных машин (64-битная Windows 7, Core 2 Quad Q9400 @ 2,66 ГГц2,67 ГГц, 4 ГБ) Но когда я использовал другую машину (XP SP3, Core 2 Duo 2,99 ГГц @ 3 ГГц, 3,21 ГБ памяти), процесс зависает при создании схемы данных, и консоль отчаянно молчит после отправки следующего сообщения:

[hibernatetool] Запуск инструмента Hibernate с конфигурацией JPA Предупреждение: ссылка не компилируется.classpath.id УСТАНОВЛЕН во время выполнения, цель БЫЛА ВО ВРЕМЯ найден разбор файла сборки, Попытка решить.Будущие версии Ant могут поддерживать ссылочные идентификаторы, определенные в невыполненных целях.

[Hibernatetool] 1. Задача: hbm2ddl (Генерирует схему базы данных).

Вы столкнулись с проблемойкак это?У вас есть решение для меня?Я открыт для любого решения.Примечание: мой скрипт ant выглядит следующим образом:

<project>
..
  <target name="create-jpa-schema">
      <tstamp>
         <format property="timestamp.for.sql" pattern="yyyy-MM-dd_HH-mm-ss" />
      </ Tstamp>
      <hibernatetool destdir="${build.sql.dir}">
         <classpath>
            <path refid="classpath.id" />
            <pathelement path="${model.jar}" />
         </ Classpath>

         <jpaconfiguration persistenceunit="studio-pu" />
         <! - Export schema to SQL database and run it Against ->
         <Hbm2ddl drop = "false" update = "true" create = "true" export = "true" outputfilename = "$ {schema_ timestamp.for.sql}. Sql" delimiter = "" format = "true" haltOnError = "true "/>
      </ Hibernatetool>
   </ Target>
..
</ Project>

РЕДАКТИРОВАТЬ: Код, выполняющий runtime.exec:

public static int executeCommand(
      String cmd,
      File directory) throws IOException, InterruptedException
   {
      Process process = Runtime.getRuntime().exec(cmd, null, directory);
      StreamReader outputStreamReader = new StreamReader(
         process.getInputStream(),
         "OUTPUT");
      StreamReader errorStreamReader = new StreamReader(process.getErrorStream(), "ERROR");
      final Thread outputThreadReader = new Thread(outputStreamReader);
      final Thread errorThreadReader = new Thread(errorStreamReader);

      outputThreadReader.start();
      errorThreadReader.start();

      int exitCode = process.waitFor();
      System.out.println("exit code:" + exitCode);
      return exitCode;

   }

StreamReader.java

public class StreamReader implements Runnable
{
   InputStream is;

   OutputStream os;

   String type;   

   StreamReader(InputStream is, String type)
   {
      this.is = is;
      this.type = type;
   }

   StreamReader(InputStream is, OutputStream os, String type)
   {
      this.is = is;
      this.os = os;
      this.type = type;
   }

   @Override
   public void run()
   {
      try
      {
         PrintWriter pw = null;

         if (os != null)
            pw = new PrintWriter(os);

            InputStreamReader isr = new InputStreamReader(is);

            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null)
            {
               if (pw != null)
               {
                  pw.println(line);
                  pw.flush();
               }
               else
                  System.out.println(type + ">" + line);
               if(progressListener!=null)
               progressListener.onUpdate(line);
            }

      }
      catch (IOException ioe)
      {
         ioe.printStackTrace();
      }

   }

}

Ответы [ 3 ]

1 голос
/ 26 августа 2011

Добавить System.out.println() до и после readLine() в StreamReader. Выясните, активно ли оно продолжает читать, когда консоль зависает, или поток завершился преждевременно.

1 голос
/ 26 августа 2011

Является ли экспортируемая схема особенно большой?Будет ли он выводить много?

В задаче муравья hbm2ddl есть атрибут 'console', который, если console="true", копирует ddl в System.out.println(), что может быть причиной вашей проблемы.Это может испортить буферизацию на вашем XP.

По умолчанию console = "true".Попробуйте с console = "false".

<Hbm2ddl console="false" drop = "false" update = "true" create = "true" export = "true" outputfilename = "$ {schema_ timestamp.for.sql}. Sql" delimiter = "" format = "true" haltOnError = "true "/>

Для получения дополнительной информации см. Код задачи Ant Hbm2ddl

1 голос
/ 19 августа 2011

Я не уверен, что это возможно, но вы рассматривали возможность вызова муравья программно, вместо запуска нового процесса?

Согласно этой статье , вы должны быть в состоянии сделать следующее в новом потоке вместо того, чтобы порождать процесс:

File buildFile = new File("build.xml");
Project p = new Project();
p.setUserProperty("ant.file", buildFile.getAbsolutePath());
p.init();
ProjectHelper helper = ProjectHelper.getProjectHelper();
p.addReference("ant.projectHelper", helper);
helper.parse(p, buildFile);
p.executeTarget(p.getDefaultTarget());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...