ChatGPT解决这个技术问题 Extra ChatGPT

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

Many times, a Java app needs to connect to the Internet. The most common example happens when it is reading an XML file and needs to download its schema.

I am behind a proxy server. How can I set my JVM to use the proxy ?

The Oracle documentation around this seems pretty stale (though still probably valid). Here's something more modern from Spring: docs.spring.io/spring-integration/reference/html/…

S
Stephen Ostermiller

From the Java documentation (not the javadoc API):

http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html

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). Here's the example with the Unix shell script:

JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...

When using containers such as JBoss or WebLogic, my solution is to edit the start-up scripts supplied by the vendor.

Many developers are familiar with the Java API (javadocs), but many times the rest of the documentation is overlooked. It contains a lot of interesting information: http://download.oracle.com/javase/6/docs/technotes/guides/

Update : If you do not want to use proxy to resolve some local/intranet hosts, check out the comment from @Tomalak:

Also don't forget the http.nonProxyHosts property!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.example.com|etc"

Hi guys, how can you include the username and password in this also? Thanks
@Joeblackdev look at http.proxyUser and http.proxyPassword
On my experience: to find the proxy address go to IE -> InternetOptions-> Lan setttings
@aasukisuki http.proxyUser and http.proxyPassword are not Java system properties. They are for the Apache HTTP client.
Also, don't forget to configure https.proxyHost and https.proxyPort for HTTPs.
T
Thiago Negri

To use the system proxy setup:

java -Djava.net.useSystemProxies=true ...

Or programatically:

System.setProperty("java.net.useSystemProxies", "true");

Source: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html


Awesome setting jvm arguement works for me like charm.. Thanks
I used this code to disable the proxy by "false" value on my SSLSocket. Thanks.
Perhaps it is because my proxy requires authentication, but this did not work for me. I wish it did.
This does not work with Proxy Auto-Config (PAC) files, see stackoverflow.com/questions/10324996/…
This is not working although it shows in VM arguments . Any help appriciated
C
Chris Carruthers

To set an HTTP/HTTPS and/or SOCKS proxy programmatically:

...

public void setProxy() {
    if (isUseHTTPProxy()) {
        // HTTP/HTTPS Proxy
        System.setProperty("http.proxyHost", getHTTPHost());
        System.setProperty("http.proxyPort", getHTTPPort());
        System.setProperty("https.proxyHost", getHTTPHost());
        System.setProperty("https.proxyPort", getHTTPPort());
        if (isUseHTTPAuth()) {
            String encoded = new String(Base64.encodeBase64((getHTTPUsername() + ":" + getHTTPPassword()).getBytes()));
            con.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
            Authenticator.setDefault(new ProxyAuth(getHTTPUsername(), getHTTPPassword()));
        }
    }
    if (isUseSOCKSProxy()) {
        // SOCKS Proxy
        System.setProperty("socksProxyHost", getSOCKSHost());
        System.setProperty("socksProxyPort", getSOCKSPort());
        if (isUseSOCKSAuth()) {
            System.setProperty("java.net.socks.username", getSOCKSUsername());
            System.setProperty("java.net.socks.password", getSOCKSPassword());
            Authenticator.setDefault(new ProxyAuth(getSOCKSUsername(), getSOCKSPassword()));
        }
    }
}

...

public class ProxyAuth extends Authenticator {
    private PasswordAuthentication auth;

    private ProxyAuth(String user, String password) {
        auth = new PasswordAuthentication(user, password == null ? new char[]{} : password.toCharArray());
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return auth;
    }
}

...

Remember that HTTP proxies and SOCKS proxies operate at different levels in the network stack, so you can use one or the other or both.


If "java.net.socks.username/password" are set, why also set an Authenticator?
why isn't "con.setRequest..." the con isn't recognized. What libraries are needed for this.
+1 for the socks proxy option as sometimes http proxy can't solve my problem
In my testing, it works if you only set the default Authenticator—no need to set the authentication properties
Doesn't work if you only the system properties. Methinks the java.net.socks.(username|password) properties do nothing.
A
Alok Nair

You can set those flags programmatically this way:

if (needsProxy()) {
    System.setProperty("http.proxyHost",getProxyHost());
    System.setProperty("http.proxyPort",getProxyPort());
} else {
    System.setProperty("http.proxyHost","");
    System.setProperty("http.proxyPort","");
}

Just return the right values from the methods needsProxy(), getProxyHost() and getProxyPort() and you can call this code snippet whenever you want.


"proxySet" does nothing. Proof: set it to "false". There is not and has never been such a property in the JDK, various books and online references notwithstanding. It came from the long-defunct HotJavaBean, an encapsulated browser, died a death in about 1998.
Really are the property names without http/https ?
This is wrong on three counts: 1: as mentioned, there is no "proxySet" item; 2: "proxyHost" and "proxyPort" need to be "http.proxyHost" and "http.proxyPort" (or the 'https' equivalent); 3: System.getProperties().put(X,Y) is not the same as System.setProperty(X,Y). Other than that, though - great answer.
@RobCranfill 1: "proxySet" used to be a non-standard flag that was needed by an old JDK but is not necessary anymore; 2: "proxyHost" and "proxyPort" do work, the "http." prefix just restricts them to the HTTP protocol (similar for "https."), 3: here you're right.
M
Martijn Pieters

JVM uses the proxy to make HTTP calls

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");

This may use user setting proxy

System.setProperty("java.net.useSystemProxies", "true");

Use System.setProperty instead of System.getProperties().put(...)
M
MadBoomy

Combining Sorter's and javabrett/Leonel's answers:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar

M
Mihai Capotă

Set the java.net.useSystemProxies property to true. You can set it, for example, through the JAVA_TOOL_OPTIONS environmental variable. In Ubuntu, you can, for example, add the following line to .bashrc:

export JAVA_TOOL_OPTIONS+=" -Djava.net.useSystemProxies=true"


A
Alex. S.

You can set some properties about the proxy server as jvm parameters

-Dhttp.proxyPort=8080, proxyHost, etc.

but if you need pass through an authenticating proxy, you need an authenticator like this example:

ProxyAuthenticator.java

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

public class ProxyAuthenticator extends Authenticator {

    private String userName, password;

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(userName, password.toCharArray());
    }

    public ProxyAuthenticator(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
}

Example.java

    import java.net.Authenticator;
    import ProxyAuthenticator;

public class Example {

    public static void main(String[] args) {
        String username = System.getProperty("proxy.authentication.username");
        String password = System.getProperty("proxy.authentication.password");

                if (username != null && !username.equals("")) {
            Authenticator.setDefault(new ProxyAuthenticator(username, password));
        }

                // here your JVM will be authenticated

    }
}

Based on this reply: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E


this does not work. if you are not already authenticated the first line in the main function gets a bunch of null values and the code stops. This doesn't help someone authenticate their jvm so that they can make URL calls through a proxy.
G
Gilad Peleg

The following shows how to set in Java a proxy with proxy user and proxy password from the command line, which is a very common case. You should not save passwords and hosts in the code, as a rule in the first place.

Passing the system properties in command line with -D and setting them in the code with System.setProperty("name", "value") is equivalent.

But note this

Example that works:

C:\temp>java -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps.proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit com.andreas.JavaNetHttpConnection

But the following does not work:

C:\temp>java com.andreas.JavaNetHttpConnection -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps=proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit

The only difference is the position of the system properties! (before and after the class)

If you have special characters in password, you are allowed to put it in quotes "@MyPass123%", like in the above example.

If you access an HTTPS service, you have to use https.proxyHost, https.proxyPort etc.

If you access an HTTP service, you have to use http.proxyHost, http.proxyPort etc.


ProxyUser and proxyPassword are not Java system properties, but Apache HTTP client properties so this doesn't work in all cases.
J
John M

reading an XML file and needs to download its schema

If you are counting on retrieving schemas or DTDs over the internet, you're building a slow, chatty, fragile application. What happens when that remote server hosting the file takes planned or unplanned downtime? Your app breaks. Is that OK?

See http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files

URL's for schemas and the like are best thought of as unique identifiers. Not as requests to actually access that file remotely. Do some google searching on "XML catalog". An XML catalog allows you to host such resources locally, resolving the slowness, chattiness and fragility.

It's basically a permanently cached copy of the remote content. And that's OK, since the remote content will never change. If there's ever an update, it'd be at a different URL. Making the actual retrieval of the resource over the internet especially silly.


M
Marcelo C.

If you want "Socks Proxy", inform the "socksProxyHost" and "socksProxyPort" VM arguments.

e.g.

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main

L
Lonzak

I am also behind firewall, this worked for me!!

System.setProperty("http.proxyHost", "proxy host addr");
System.setProperty("http.proxyPort", "808");
Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication("domain\\user","password".toCharArray());
    }
});

URL url = new URL("http://www.google.com/");
URLConnection con = url.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));

// Read it ...
String inputLine;
while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

in.close();

S
Sorter

Add this before you connect to a URL behind a proxy.

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");

http.proxyUser and http.proxyPassword are not Java system properties. They are for the Apache HTTP client.
Use System.setProperty instead of System.getProperties().put(...)
P
Philip M.

This is a minor update, but since Java 7, proxy connections can now be created programmatically rather than through system properties. This may be useful if:

Proxy needs to be dynamically rotated during the program's runtime Multiple parallel proxies need to be used Or just make your code cleaner :)

Here's a contrived example in groovy:

// proxy configuration read from file resource under "proxyFileName"
String proxyFileName = "proxy.txt"
String proxyPort = "1234"
String url = "http://www.promised.land"
File testProxyFile = new File(proxyFileName)
URLConnection connection

if (!testProxyFile.exists()) {

    logger.debug "proxyFileName doesn't exist.  Bypassing connection via proxy."
    connection = url.toURL().openConnection()

} else {
    String proxyAddress = testProxyFile.text
    connection = url.toURL().openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort)))
}

try {
    connection.connect()
}
catch (Exception e) {
    logger.error e.printStackTrace()
}

Full Reference: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html


This is since Java 1.5, not 1.7.
d
dma_k

Recently I've discovered the way to allow JVM to use browser proxy settings. What you need to do is to add ${java.home}/lib/deploy.jar to your project and to init the library like the following:

import com.sun.deploy.net.proxy.DeployProxySelector;
import com.sun.deploy.services.PlatformType;
import com.sun.deploy.services.ServiceManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class ExtendedProxyManager {

    private static final Log logger = LogFactory.getLog(ExtendedProxyManager.class);

    /**
     * After calling this method, proxy settings can be magically retrieved from default browser settings.
     */
    public static boolean init() {
        logger.debug("Init started");

        // Initialization code was taken from com.sun.deploy.ClientContainer:
        ServiceManager
                .setService(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? PlatformType.STANDALONE_TIGER_WIN32
                        : PlatformType.STANDALONE_TIGER_UNIX);

        try {
            // This will call ProxySelector.setDefault():
            DeployProxySelector.reset();
        } catch (Throwable throwable) {
            logger.error("Unable to initialize extended dynamic browser proxy settings support.", throwable);

            return false;
        }

        return true;
    }
}

Afterwards the proxy settings are available to Java API via java.net.ProxySelector.

The only problem with this approach is that you need to start JVM with deploy.jar in bootclasspath e.g. java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. If somebody knows how to overcome this limitation, let me know.


I wish I could upvote this multiple times, it is the only solution that worked for me; thank you! I had to download the apache commons logging jar from here: commons.apache.org/proper/commons-logging/download_logging.cgi My code in Main(): System.setProperty("java.net.useSystemProxies", "true"); System.out.println("detecting proxies"); ExtendedProxyManager.init();
What would the xbootclasspath pointing to deploy.jar have for effect, couldn't i take that jar onto my normal classpath (when running without webstart)?
in JDK 9, it fails :( Exception in thread "main" java.lang.IllegalAccessError: class ...) cannot access class com.sun.deploy.net.proxy.DeployProxySelector (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.proxy
V
Viet Tran

That works for me:

public void setHttpProxy(boolean isNeedProxy) {
    if (isNeedProxy) {
        System.setProperty("http.proxyHost", getProxyHost());
        System.setProperty("http.proxyPort", getProxyPort());
    } else {
        System.clearProperty("http.proxyHost");
        System.clearProperty("http.proxyPort");
    }
}

P/S: I base on GHad's answer.


This answer doesn't provide anything that hasn't already been said in the other answers.
C
Community

As is pointed out in other answers, if you need to use Authenticated proxies, there's no reliable way to do this purely using command-line variables - which is annoying if you're using someone else's application and don't want to mess with the source code.

Will Iverson makes the helpful suggestion over at Using HttpProxy to connect to a host with preemtive authentication to use a Proxy-management tool such as Proxifier ( http://www.proxifier.com/ for Mac OS X and Windows) to handle this.

For example with Proxifier you can set it up to only intercept java commands to be managed and redirected through its (authenticated) proxy. You're going to want to set the proxyHost and proxyPort values to blank in this case though, e.g. pass in -Dhttp.proxyHost= -Dhttp.proxyPort= to your java commands.


J
Jakub Partyka

This is a complete example that worked for me - note that for HTTPS there are separate properties (as per https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html).

Code below sends a request to https://api.myip.com API and prints the response.

public static void main(String[] args) throws IOException {
    System.setProperty("java.net.useSystemProxies", "true");
    final String proxyUser = "lum-customer-c_f95783f5-zone-datacenter-ip-92.240.207.56";
    final String proxyPass = "s3mgwrx2b628";
    final String host = "zproxy.lum-superproxy.io";
    final Integer port = 22225;

    // http
    System.setProperty("http.proxyHost",host);
    System.setProperty("http.proxyPort", String.valueOf(port));
    System.setProperty("http.proxyUser", proxyUser);
    System.setProperty("http.proxyPassword", proxyPass);

    // https
    System.setProperty("https.proxyHost",host);
    System.setProperty("https.proxyPort", String.valueOf(port));
    System.setProperty("https.proxyUser", proxyUser);
    System.setProperty("https.proxyPassword", proxyPass);

    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
    System.setProperty("jdk.https.auth.tunneling.disabledSchemes", "");

    Authenticator.setDefault(new Authenticator() {
                @Override
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(proxyUser, proxyPass.toCharArray());
                }
        }
    );

    // create and send a https request to myip.com API
    URL url = new URL("https://api.myip.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    int status = connection.getResponseCode();
    
    // read the response
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String responseLine;
    StringBuffer responseContent = new StringBuffer();
    while ((responseLine = in.readLine()) != null) 
        responseContent.append(responseLine);
    
    in.close();
    connection.disconnect();
    
    // print the response
    System.out.println(status);
    System.out.println(responseContent);
}

佚名

You can utilize the http.proxy* JVM variables if you're within a standalone JVM but you SHOULD NOT modify their startup scripts and/or do this within your application server (except maybe jboss or tomcat). Instead you should utilize the JAVA Proxy API (not System.setProperty) or utilize the vendor's own configuration options. Both WebSphere and WebLogic have very defined ways of setting up the proxies that are far more powerful than the J2SE one. Additionally, for WebSphere and WebLogic you will likely break your application server in little ways by overriding the startup scripts (particularly the server's interop processes as you might be telling them to use your proxy as well...).


n
nylas

I think configuring WINHTTP will also work.

Many programs including Windows Updates are having problems behind proxy. By setting up WINHTTP will always fix this kind of problems