Java HttpURLConnection神秘地死了

时间:2013-03-01 14:32:28

标签: java try-catch httpurlconnection http-get

我正在尝试使用java.net.HttpURLConnection进行简单的HTTP GET调用并遇到无法解释的问题:

public String makeGETCall(HttpURLConnection con) {
    try {
        System.out.println("About to make the request...");

        if(con == null)
            System.out.println("con is NULL");
        else {
            System.out.println("con is NOT null");

            if(con.getInputStream() == null)
                System.out.println("con's input stream is NULL");
            else
                System.out.println("con's input stream is NOT null");
        }
    } catch(Throwable t) {
        System.out.println("Error: " + t.getMessage());
    }

    System.out.println("Returning...")
    return "DUMMY DATA";
}

当我运行它时,我得到以下控制台输出:

About to make the request...
con is NOT null

然后程序终止,没有错误。没有异常被抛出,它不会意外退出,并且它不会挂起或超时......它就会死掉。

当我con.getInputStream()检查null时,它似乎正在消亡。但这仍然无法解释为什么它只是在没有任何错误迹象的情况下悄然死亡。有任何想法吗?我愿意承认我本可以错误地创建HttpURLConnection,但是仍然应该有更多关于杀死我的程序的指示......提前致谢!

4 个答案:

答案 0 :(得分:1)

您的代码不应该编译,因为这一行:

 System.out.println("Returning...")

缺少分号。话虽如此,我想你正在使用的应用程序的任何运行都使用旧的执行,并且没有你可能编写的新代码。

如果情况并非如此,那么你已经错误地粘贴了你的代码(某种程度上),我猜想你错过了我们需要看到的其他方面?如果您已经以某种方式为StackOverflow编辑了代码,您会介意共享原始文件吗?

此外,除非您有充分的理由,否则我建议不要抓住Throwable。掩盖应用程序错误通常是不好的做法。

答案 1 :(得分:0)

  

当我检查con.getInputStream()是否为空时,它似乎正在消亡。

我觉得很难相信。

从表面上看:

  • 测试引用以查看它是否null无法终止您的程序

  • con.getInputStream()可以抛出异常或返回

  • 如果确实返回则不应该返回null ...'因为API不允许它...并且您会看到一条消息

  • 如果抛出异常,您会看到Error: ...消息

我的结论是,不同的线程导致应用程序退出,或者应用程序根本没有退出。

我能想到的唯一其他解释是你的编辑/编译/部署/运行程序不起作用,而且实际运行的代码与你正在使用的代码不匹配。

我建议您尝试为此创建一个SSCCE,以便其他人可以重现它并找出实际发生的情况。

答案 2 :(得分:0)

这里也有同样的问题。我跟踪了我的代码,它永远停留在con.getInputStream()。 要重现问题,请运行下面的代码示例。 (输入正确的网址)

A)在另一台主机上启动任何HTTPS服务器

B)启动客户端代码

C)关闭HTTPS服务器

D)再次启动HTTPS服务器

- >卡在con.getInputStream()

重新启动HTTPS服务器时,似乎客户端出现了一些死锁。 仅供参考我使用捆绑org.apache.felix.http.jetty作为HTTP(S)-Server并附加了Restlet Servlet。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class TestHTTPS{

public static void main(String[] args) throws InterruptedException
{
    new TestHTTPS().activate();
}

private void activate() throws InterruptedException{

    TrustManager[] insecureTrustManager = new TrustManager[] { 
            new X509TrustManager() {     
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                } 
                public void checkClientTrusted( 
                    java.security.cert.X509Certificate[] certs, String authType) {
                    } 
                public void checkServerTrusted( 
                    java.security.cert.X509Certificate[] certs, String authType) {
                }
            } 
        }; 


    try {
        SSLContext sc = SSLContext.getInstance("SSL"); 
        sc.init(null, insecureTrustManager, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } 

    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

    String https_url = "https://192.168.xx.xx:8443";
    URL url;
    try {

        url = new URL(https_url);

        while(true) {
            HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
            con.setConnectTimeout(1000);
            print_content(con);
            Thread.sleep(100);
        }

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void print_content(HttpsURLConnection con){
    if(con!=null){

        try {

            System.out.println("****** Content of the URL ********");           
            BufferedReader br = 
                    new BufferedReader(
                            new InputStreamReader(con.getInputStream()));

            String input;

            while ((input = br.readLine()) != null){
                System.out.println(input);
            }
            br.close();

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

欢迎任何建议。

答案 3 :(得分:0)

修正了它。

con.setReadTimeout(1000)

显然,HTTP Server接受连接,但在服务器启动时错误的时刻连接时无法满足请求。 setReadTimeout导致线程抛出SocketTimeoutException。

希望这有助于其他人解决问题...

由于在使用RESTlet和内部连接器时也可能出现此问题,因此这是RESTlet的解决方案。您必须自己处理hostnameVerifier和SSLContextFactory:

context = new Context();

context.getParameters().add("readTimeout", Integer.toString(1000));
context.getAttributes().put("sslContextFactory", new YourSslContextFactory());
context.getAttributes().put("hostnameVerifier", new YourHostnameVerifier());

client = new Client(context, Protocol.HTTPS);

确保

org.restlet.ext.ssl 
org.restlet.ext.net
org.restlet.ext.httpclient 

在你的类路径中。

最好的问候