Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java http proxy setting is cached until JVM restart

Tags:

java

http

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";
  }
}
like image 879
Alex Avatar asked Nov 10 '11 11:11

Alex


People also ask

How do I set the proxy to be used by the JVM?

Set the JVM flags http. proxyHost and http. proxyPort when starting your JVM on the command line. This is usually done in a shell script (in Unix) or bat file (in Windows).

Does Java use Http_proxy?

Java provides proxy handlers for HTTP, HTTPS, FTP, and SOCKS protocols. A proxy can be defined for each handler as a hostname and port number: http. proxyHost – The hostname of the HTTP proxy server.

What is nonProxyHosts?

http.nonProxyHosts (default: localhost|127.*|[::1]) Indicates the hosts that should be accessed without going through the proxy. Typically this defines internal hosts. The value of this property is a list of hosts, separated by the '|' character.

What is Java useSystemProxies?

If the system property java. net. useSystemProxies is set to true (by default it is set to false for compatibility sake), then the default ProxySelector will try to use these settings. You can set that system property on the command line, or you can edit the JRE installation file lib/net.


2 Answers

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.

like image 159
suitm Avatar answered Sep 23 '22 05:09

suitm


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);
  }

}
like image 37
Alex Avatar answered Sep 19 '22 05:09

Alex