HtmlUnit WebClient.getPage(locationToPing) блокируется при вызове jar из Runtime.exec()

#htmlunit #runtime.exec

#htmlunit #runtime.exec

Вопрос:

Я пишу приложение, которому необходимо периодически загружать jar. Jar извлекает содержимое веб-сайта, использующего HtmlUnit.Когда этот jar запускается из командной строки commond, он выполняется как ожидалось. Но когда я запускаю его с использованием Java-кода с использованием среды выполнения, он блокируется в месте, страница= WebClient.getPage(locationToPing); и не выполняется дальше.

Jar содержит только один класс Java, как указано ниже,

 package tempproj2;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Fetcher {

String locationToPing;
volatile WebClient webClient = new WebClient(BrowserVersion.FIREFOX_3_6);
HtmlPage page ;
public static final long SLEEP_TIME_IF_CONNECTION_WAS_REFUSED=10000; //SECS
public long connectionRefusedTime=0;

private static Fetcher theOnlyInstanceOfThisClass=new Fetcher();

public static Fetcher getInstance(){
    return theOnlyInstanceOfThisClass;
}
private Fetcher(){
    init();
    fetchUsingGet();
}
private void init(){
    locationToPing="http://www.mail.yahoo.com";
}

private  void fetchUsingGet(){
    try {
        System.out.println("-----------Start  1 --------------")            ;
        webClient.setUseInsecureSSL(true);
        webClient.setThrowExceptionOnScriptError(false);
        System.out.println("-----------Start  2 --------------")            ;
        webClient.setJavaScriptEnabled(true);
        System.out.println("-----------Start  3 --------------")            ;
        webClient.setTimeout(5000);  //30 secs - its int n not long be careful abt it.
        System.out.println("-----------Start  4 --------------locationToPing=" locationToPing)            ;
        page= webClient.getPage(locationToPing);
        System.out.println("-----------Start  5 --------------" page.asXml())            ;
    } catch (Exception ex) {
        System.out.println("-----------IC Fetecher     Error here --------------" ex.getMessage())            ;
        connectionRefusedTime=System.currentTimeMillis();
       ex.printStackTrace();
    }
}

private void reload(){

    if(page==null){
        fetchUsingGet();
        return;
    }
    try {

        page=(HtmlPage)page.refresh();
    } catch (java.net.SocketTimeoutException ex) {
        fetchUsingGet();
        ex.printStackTrace();
    }catch(IOException ex){
        ex.printStackTrace();
    }
}


public static void main(String ar[]){
    Fetcher fetcher=new Fetcher();
    while(true){
        try {
            Thread.sleep(4*1000);
        } catch (InterruptedException ex) {
            Logger.getLogger(Fetcher.class.getName()).log(Level.SEVERE, null, ex);
        }
        fetcher.reload();

    }


}
  

}

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

  1. Запустите класс как есть — работает нормально.
  2. Создайте Jar указанного выше класса и запустите из командной строки, используя java -jar , command — выполняется нормально.
  3. Создайте Jar указанного выше класса и запустите его из другого класса Java, используя следующий код,

     try {
        String execCmd="java -jar " downloadApplicationJarLocation.getAbsolutePath();
        Process pr=Runtime.getRuntime().exec(execCmd) ;
    
            InputStreamReader is = new InputStreamReader(pr.getInputStream());
            BufferedReader br = new BufferedReader(is);
            String line = null;
            String processMessage="";
            while ((line = br.readLine()) != null) {
                System.err.println("Line 1 " line)    ;            
                processMessage =line;
            }
            System.out.println("Finished ");
            is.close();
            br.close();
    
    
    } catch (IOException ex) {
        ex.printStackTrace();
    }
      

Но когда я пытаюсь использовать приведенный выше код, выполняется только код до page= WebClient.getPage(locationToPing); и блокируется. «Start 5» никогда не выводится на экран.

  1. Я изменил приведенный выше код и вместо прямого вызова команды e Java -jar в Runtime.exec() поместил ее в пакетный файл и вызвал этот пакетный файл. Process pr=Runtime.getRuntime().exec(batchFileLocation) ; Теперь он выполняется как ожидалось и не блокирует код.Также на экране выводится надпись «Start 5».

Моему приложению необходимо периодически вызывать jar из Java и уничтожать предыдущий процесс, если таковой имеется. Поэтому вариант 4 мне не подходит, поскольку подпроцесс все еще работает, и уничтожить подпроцесс не очень просто.

Вариант 3 — идеальный способ для меня, но я совершенно не в состоянии понять, почему он блокируется и больше не выполняется? Это как-то связано с потоковой обработкой? Использую ли я HtmlUnit так, как он должен использоваться?

Заранее спасибо

Комментарии:

1. Я заставил код работать. Ранее я читал только входной поток запускаемого процесса. Я изменил код для чтения как InutStream, так и ErrorStream создаваемого процесса, и это решило проблему.

2. Есть хорошая статья о подводных камнях создания процесса на Java javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1