简体   繁体   中英

java http proxy setting is cached until JVM restart

I'm trying to change the proxy setting for JVM in my User Interface (Eclipse Application running on Java 1.6.0.23)

if (isUseProxy()) {
    System.setProperty("java.net.useSystemProxies", "true");
    System.setProperty("http.proxyHost", getProxyHost());
    System.setProperty("http.proxyPort", getProxyPort());
    System.setProperty("https.proxyHost", getProxyHost());
    System.setProperty("https.proxyPort", getProxyPort());
    ..........
} else {
    System.clearProperty("http.proxyHost");
    System.clearProperty("http.proxyPort");
    System.clearProperty("https.proxyHost");
    System.clearProperty("https.proxyPort");
}

the problem is that the NEW proxy server value is not used until the JVM restart, it's cached somewhere in Java.

Java version:

java.runtime.version=1.6.0_26-b03
java.specification.name=Java Platform API Specification
java.specification.vendor=Sun Microsystems Inc.

UPDATE: magic continues... I tried isolating the problem to figure out how Java magically works with system.properties. Looks like Java ignores the invalid proxy server setting in some random cases. This test fails:

import org.junit.Test;

import java.io.IOException;
import java.net.*;

import static org.junit.Assert.fail;

public class ProxySetTest {

  @Test
  public void verifyProxyIsNotCachedInJVM() throws IOException {

    tryConnectionToGoogleCom();

    System.setProperty("http.proxyHost", getInvalidProxyHost());
    System.setProperty("http.proxyPort", getInvalidProxyPort()+"");
    System.setProperty("https.proxyHost", getInvalidProxyHost());
    System.setProperty("https.proxyPort", getInvalidProxyPort()+"");

    // Next connection will be through the invalid proxy. must fail?
    try {
      tryConnectionToGoogleCom();
      fail("must have failed with an exception because of invalid proxy setting");
    } catch (Exception e) {
      System.out.println("received exception: " + e);
    }

    // clear the proxy setting and try connecting again - must succeed
    System.clearProperty("http.proxyHost");
    System.clearProperty("http.proxyPort");
    System.clearProperty("https.proxyHost");
    System.clearProperty("https.proxyPort");

    // and without proxy again
    tryConnectionToGoogleCom();
  }

  private void tryConnectionToGoogleCom() throws IOException {
    URL url = new URL("http://google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.connect();
  }

  private int getInvalidProxyPort() {
    return 1234;
  }

  private String getInvalidProxyHost() {
    return "asd";
  }
}

So I am having the exact same issue and have tracked it down to axis caching the information.

It is in org.apache.axis.components.net.TransportClientPropertiesFactory

The method in question is:

public static TransportClientProperties create(String protocol)
{
    TransportClientProperties tcp =
        (TransportClientProperties)cache.get(protocol);

    if (tcp == null) {
        tcp = (TransportClientProperties)
            AxisProperties.newInstance(TransportClientProperties.class,
                                       (Class)defaults.get(protocol));

        if (tcp != null) {
            cache.put(protocol, tcp);
        }
    }

    return tcp;
}

On the first call, the tcp object gets created with whatever the current JVM settings are for the proxy. On subsequent calls, it is pulling the cached version, so even if you have changed the proxy settings in the JVM, it doesn't matter. Looking to see if I can find a way to clear the cache.

package com.alskor;

import org.junit.Test;

import java.io.IOException;
import java.net.*;

import static org.junit.Assert.fail;

public class ProxySetTest {

  @Test
  public void verifyProxyIsNotCachedInJVM() throws IOException {

    tryConnectionToGoogleCom();

    ProxySelector savedSelector = ProxySelector.getDefault();
    java.net.ProxySelector.setDefault(new FixedProxySelector(getInvalidProxyHost(), getInvalidProxyPort()));

    // Next connection will be through the invalid proxy. must fail?
    try {
      tryConnectionToGoogleCom();
      fail("must have failed with an exception because of invalid proxy setting");
    } catch (Exception e) {
      System.out.println("received exception: " + e);
    }

    // clear the proxy setting and try connecting again - must succeed
    java.net.ProxySelector.setDefault(savedSelector);
    // and without proxy again
    tryConnectionToGoogleCom();
  }

  private void tryConnectionToGoogleCom() throws IOException {
    URL url = new URL("http://google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.connect();
  }

  private int getInvalidProxyPort() {
    return 1234;
  }

  private String getInvalidProxyHost() {
    return "asd";
  }
}

package com.alskor;

import sun.misc.RegexpPool;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

public class FixedProxySelector extends ProxySelector {

  private final String host;
  private final int port;

  public FixedProxySelector(String host, int port) {
    this.host = host;
    this.port = port;
  }

  @Override
  public java.util.List<Proxy> select(URI uri) {
    if (uri == null) {
      throw new IllegalArgumentException("URI can't be null.");
    }
    List<Proxy> proxies = new ArrayList<Proxy>();
    SocketAddress addr = new InetSocketAddress(host, port);
    proxies.add(new Proxy(Proxy.Type.SOCKS, addr));
    proxies.add(new Proxy(Proxy.Type.HTTP, addr));

    return proxies;
  }

  @Override
  public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
    if (uri == null || sa == null || ioe == null) {
      throw new IllegalArgumentException("Arguments can't be null.");
    }
    throw new RuntimeException(ioe.toString(), ioe);
  }

}

Pass java.net.Proxy object to URL.openConnection(Proxy) method. You could use Proxy.NO_PROXY for direct connection. Or create new proxy like this:

new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080))

Here is a full sample:

public class TestConnectOverProxy {

  static class Connector {
    private Proxy proxy = Proxy.NO_PROXY;

    public void setProxy(Proxy proxy) {
      this.proxy = proxy;
    }

    /**
     * This method works with java.net.Proxy field of the Connector class
     * as described
     * <a href="http://www.rgagnon.com/javadetails/java-0085.html">here</a>
     */
    public String getContent(URL url) throws IOException {
      HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
      conn.connect();
      System.out.println(conn.getRequestMethod());
      System.out.println(conn.getResponseCode());
      return IOUtils.toString(conn.getInputStream());
    }
  }

  @Test
  public void test() throws IOException {
    URL url = new URL("http://www.google.com");
    Connector connector = new Connector();


    //connect directly
    connector.setProxy(Proxy.NO_PROXY);
    System.out.println(connector.getContent(url));

    //connect over proxy
    connector.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080)));
    System.out.println(connector.getContent(url));
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM