I am facing a problem with JVM and DNS.
Everything I'm reading (including the docs and this) says that I can disable JVM DNS caching using networkaddress.cache.ttl, which can be set using java.security.Security.setProperties, but through the standard approach of using system properties. I have successfully changed this to 0, so no more caching in my JVM.
But now, on each call of InetAddress.getByName("mytest.com"), it seems that my JVM is using the system DNS cache (in my case Windows 8). Indeed, between 2 calls of the method, I have changed the BIND9 properties for "mytest.com", but the IP return is still the same. Here is the workflow:
setCachePolicyInJVM(0) in my Java code.
set mytest.com to 192.168.1.188 in BIND9, restart.
InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.188
set mytest.com -> 192.168.1.160 in BIND9, restart.
InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.188 (should be 160 if there was no caching).
Flush the Windows DNS
InetAddress.getByName("mytest.com").getHostAddress(); -> 192.168.1.160
I have read several times that the JVM does not use the system cache, but that is wrong: it clearly does.
How do we force a new DNS resolution on each call, bypassing the OS DNS cache?
I think I've run into this problem, or a very similar one. What I did then was to implement my own DNS provider for the JVM, see how to change the java dns service provider for details. You can use the dnsjava mentioned there or roll your own.
You can either edit your $JAVA_HOME/jre/lib/security/java.security for Java 6-8 and $JAVA_HOME/conf/security/java.security property file to add the following property .
networkaddress.cache.ttl=1
It is not available to set it in command line.
Since these 2 properties are part of the security policy, they are not
set by either the -D option or the System.setProperty() API, instead
they are set as security properties.
To set this property inside the code, you can use the following method.
java.security.Security.setProperty("networkaddress.cache.ttl", "1")
Or add the following property in the java command line.
-Dnetworkaddress.cache.ttl=1
It is also important to note that values are effective only if the corresponding networkaddress.cache.* properties are not set.
See Java 8 Networking Properties, Java 9 Networking Properties and VeriSign DNS Caching in Java Virtual Machines for more details.
This answer also adds some details.
From here it seems you should set sun.net.inetaddr.ttl. This worked for me.
Example from link:
java -Dsun.net.inetaddr.ttl=1 test
Enter the hostname
rrr
Output isrrr/129.145.146.100
Enter the hostname
rrr
Output isrrr/129.147.146.100
Related
I'm looking for a java argument (or perhaps some different method) to allow me to specify a file to be used by the JVM as the java.security file, rather than using the one found in the JDK (in the JRE lib).
To give you a little more context, I am working with a WebLogic server that was set up by someone else and is running two (or more) different JVMs off the same JDK. We have run into an issue now where the work I'm doing on one JVM requires a different java.security file than the one that is currently being used by the other JVM. I am hoping there will be a way for me to just point my JVM at a new java.security file without having to point it at an entirely new JDK (due to space constraints, we would like to avoid uploading a JDK specific to each JVM).
I realize that the server's set up is not ideal, but completely rearranging the existing set up is not viable and not something I am in a position to do. So, I am hoping someone might have a creative solution that would allow for multiple JVMs running off the same JDK but with different security configurations.
I have been trying to find solutions out there, but it seems my Google-Foo is not as strong as I had hoped. Here's to hoping one of you has the answer!
Many thanks.
EDIT
Sorry maybe my original post was not clear, but I am interested in specifying the java.security file, also often referred to as the Java master security properties file, not the java.policy file which is found in the same directory.
My Solution
I will post my solution here just for reference of others who might fall into a similar situation.
As I can't seem to find an argument to specify at start up, I have decided that I will have to forgo the java.security properties file. It is possible to set properties and providers (typically configured in the file) within code using the Security class (java.security.Security). So, at least in the interim, I plan to write a class that will go through setting up my JVM specific security configurations after startup (essentially overwriting the default configurations provided by the file for the other JVM). While the obvious downside of this solution is that is does not externalize security configurations of this JVM, the solution does provide me a way to set JVM specific properties and providers without affecting the configuration of other JVMs running off the same JDK.
I appreciate the time and consideration given by others. Thanks =)
Looking at the OpenJDK source, you cannot change the loading of the java.security file. However, that file has a property called security.overridePropertiesFile which, if set to true (as it is in my current, vanilla install), allows you to load an additional security properties file specified through the system property named java.security.properties. Note also, that the command line syntax follows a similar pattern to the policy file where = specifies additional configuration and == specifies a complete replacement configuration.
Maybe the accepted answer on this thread would help you out; basically it says that you need to specify your own policy file and the final invocation should look like:
java -Djava.security.manager -Djava.security.policy=/some/path/my.policy
You can just set the system property -Djava.security.properties=***** to specify the security property you want to load, but you must set the property security.overridePropertiesFile=true prior to use this approach.
I'm creating a custom property in my WebSphere Application Server (ND 8.5.0.2) at below path as prescribed by plenty of articles on web:
Application servers > SamplesServer > Process definition > Java Virtual Machine > Custom properties
As per the articles, I can access this custom property using
System.getProperty("PropertyName");
However, it always returns NULL. I tried all the possible ways and done plenty of Googling but yet to retrieve this property.
Also, you can specify system properties in the "Generic JVM Arguments" field of the Java Virtual Machine configuration mentioned in your question. Here's a technote with the procedure: http://www-01.ibm.com/support/docview.wss?uid=swg21417365. Add each property in the form -DpName=pValue. For example: -Dcom.ibm.ws.example=true
If you are using a Deployment Manager to configure these settings, please ensure that you synchronize the configuration after saving the settings.
If you run:
$ jcmd <pid> VM.system_properties
from the host your server is running on, it will print out all system properties identified by that JVM. If you don't know what the pid is, then you can run:
$ jps
and it will show you a list of all processes along with their ids that you can use to connect to to find this information.
That will tell you whether the problem is in the way that you're setting the property, or in your code. However, from the above the code looks correct, which suggests that the custom property isn't being set in the way you are launching the process.
I'm coding my server in java, and through the day, my server has to connect through 5 different proxies at once to other servers and gather data. However, reading about java proxy settings through stackexchange, I see that when you set a proxy, its effect is VM-wide, meaning whatever network activity that .jar was doing, it will do it through a proxy if somewhere a different thread sets a proxy setting within the jar.
I'm currently using this method of setting a proxy, which according to some tests it's actually pretty functional and works fast.
System.getProperties().put( "http.proxyHost", host );
System.getProperties().put( "http.proxyPort", port );
However, I can't really afford having 5 jars doing the same thing with different proxies, I tried it to, it would be a simple solution however I can't afford to use that much ram only for this, as my server is huge.
You need to call each connection with its own proxy settings. The Answer here by NickDk defines how you can call a url with its own proxy settings. You will need to do the same with each of your 5 proxies separately.
here is described the use a library embeded in the JRE, able to handle "proxypac" files in wich any combination of proxies can be defined.
since it is embeded in the JRE, standard ways to configure a Java application with a proxypac file (standard launch optional parameters) might exist, but I am not aware of it.
Howhever the solution described in the link provided should fit your needs since your usage is programatic.
The Release Notes of JDK7u21 specified the changes related to RMI:
From this release, the RMI property java.rmi.server.useCodebaseOnly is
set to true by default. In previous releases the default value was
false.
This change of default value may cause RMI-based applications to break
unexpectedly. The typical symptom is a stack trace that contains a
java.rmi.UnmarshalException containing a nested
java.lang.ClassNotFoundException.
If these exceptions occur, the preferred way to solve the problem is
to configure all RMI clients and servers to use the same codebase, by
specifying proper values in the java.rmi.server.codebase system
property. This is typically done by adding the -D option to the
command that starts up the application: java
-Djava.rmi.server.codebase=file:////(path-to-remote-classes)/
It also specified in the documentation here that workaround is to set the java.rmi.server.useCodebaseOnly property back to false.
However, even when I explicitly set this property to false, I am getting an exception mentioned above. Any clue here please?
And if I have to solve it by the preferred way described above (by setting the -Djava.rmi.server.codebase=file:////(path-to-remote-classes)/, then which path should I set over here? My workspace/bin?
You have to make sure to set the properties on all JVMs that are using your remote classes. This includes your RMI server, the RMI clients, and the RMI registry. If they are all on the same machine, then you can set java.rmi.server.codebase on them all to a file: URL that points to the location of the classes. If they're not on the same machine, then you could make the classes available using an HTTP server, and then set the codebase property of the remote JVMs (presumably the clients) to use an http: URL that points to where the classes are available. Or you could make the classes available to remote JVMs through some other means, such as copying them, or using a shared filesystem, and then set the codebase property to a file: URL.
Your attempt to apply the workaround of setting java.rmi.server.useCodebaseOnly to false might not be working for a couple reasons: you might not have set it in all of the interacting JVMs, or you might not have set the codebase property to the right value.
Since you're having to go to the trouble of configuring the registry and all the clients, you might as well pursue setting their codebase property to the right URL, instead of pursuing the workaround of setting useCodebaseOnly to false.
You would need to either:
Set it to false at all the JVM(s) which download classes, and ensure that java.rmi.server.codebase is set to something useable at all the JVMs which send objects whose classes may need downloading, or
Leave it alone but make sure that every JVM in the system is started with a java.rmi.server.codebase property that points to a useable codebase for that JVM.
It's a very strange change to make. I don't see any security implications, just a nuisance change that changes semantics at all the codebase recipients. With useCodebaseOnly=true, you have to set java.rmi.server.codebase at the receiving JVMs, where otherwise you only have to set it at the sending JVMs. This isn't clear from the documentation.
I am sorry, I solved it on my own. The problem was wrong number of parameters were being passed to my .ksh file. This caused the problem starting RMI registry.
I'm looking for a java argument (or perhaps some different method) to allow me to specify a file to be used by the JVM as the java.security file, rather than using the one found in the JDK (in the JRE lib).
To give you a little more context, I am working with a WebLogic server that was set up by someone else and is running two (or more) different JVMs off the same JDK. We have run into an issue now where the work I'm doing on one JVM requires a different java.security file than the one that is currently being used by the other JVM. I am hoping there will be a way for me to just point my JVM at a new java.security file without having to point it at an entirely new JDK (due to space constraints, we would like to avoid uploading a JDK specific to each JVM).
I realize that the server's set up is not ideal, but completely rearranging the existing set up is not viable and not something I am in a position to do. So, I am hoping someone might have a creative solution that would allow for multiple JVMs running off the same JDK but with different security configurations.
I have been trying to find solutions out there, but it seems my Google-Foo is not as strong as I had hoped. Here's to hoping one of you has the answer!
Many thanks.
EDIT
Sorry maybe my original post was not clear, but I am interested in specifying the java.security file, also often referred to as the Java master security properties file, not the java.policy file which is found in the same directory.
My Solution
I will post my solution here just for reference of others who might fall into a similar situation.
As I can't seem to find an argument to specify at start up, I have decided that I will have to forgo the java.security properties file. It is possible to set properties and providers (typically configured in the file) within code using the Security class (java.security.Security). So, at least in the interim, I plan to write a class that will go through setting up my JVM specific security configurations after startup (essentially overwriting the default configurations provided by the file for the other JVM). While the obvious downside of this solution is that is does not externalize security configurations of this JVM, the solution does provide me a way to set JVM specific properties and providers without affecting the configuration of other JVMs running off the same JDK.
I appreciate the time and consideration given by others. Thanks =)
Looking at the OpenJDK source, you cannot change the loading of the java.security file. However, that file has a property called security.overridePropertiesFile which, if set to true (as it is in my current, vanilla install), allows you to load an additional security properties file specified through the system property named java.security.properties. Note also, that the command line syntax follows a similar pattern to the policy file where = specifies additional configuration and == specifies a complete replacement configuration.
Maybe the accepted answer on this thread would help you out; basically it says that you need to specify your own policy file and the final invocation should look like:
java -Djava.security.manager -Djava.security.policy=/some/path/my.policy
You can just set the system property -Djava.security.properties=***** to specify the security property you want to load, but you must set the property security.overridePropertiesFile=true prior to use this approach.