I have a running Java program which I would like to control at the command line by changing a custom system property which I'm listening for changes to inside the application, thereby not requiring a restart of the application for the changes to take affect.
I understand that it's possible to change some of the default JVM properties using jinfo but it doesn't seem to work for custom properties which I set at compile time using the -D flag.
For example, if I start a JAR using the following command line arguments:
java -Dfoo=1 -jar my_jar.jar
attempting to call the following fails:
jinfo -flag foo=2 'pid'
Is there something I'm missing or is this simply not possible?
This utility is unsupported and might not be available in future releases of the JDK. Official Doc
Not all of the available parameters can be changed. Reference
IMO, Recommended way is to have some event-listener or service call to change the flags of running application.
I had used some system properties using jinfo so not sure if custom flags can be changed during jar execution. Try some custom boolean flag using command jinfo -flag +<customBooleanFlag> <PID> to check if its working.
Related
From a Java application I want to run another Java application on the same Java installation but in a separate process.
AFAIK for a new process I would use ProcessBuilder to run a command like
java -jar my.jar
but what if java is in a different directory, or should be java.exe since we are on Windows, or java.exe has some other name since the first application was jlinked and jpackaged?
Edit: What I learned meanwhile is that a jpackaged application comes with a native executable that sits in front of the JVM but passes all arguments to the application. That means it is no longer possible to specify an alternative jar to be executed, and some other mechanism is necessary.
If jlink image used within jpackage based apps is built without using the --strip-native-commands flag then the runtime image will contain bin/java (or bin/java.exe and bin/javaw.exe on Windows).
This will mean that you should be able to determine a path to launch a new JVM which works inside or outside of jpackage apps just based on the current runtime's java.home and by appending extra VM arguments in normal way for the classpath and main / module of the other application.
On Windows the environment property echo %PATHEXT% usually contains .EXE so the following should specify the java executable for the current runtime without needing to add the correct file extension on Windows:
String java = Path.of(System.getProperty("java.home"),"bin", "java").toString();
You can test above inside your jpackage and non-jpackaged app with a simple one-liner (note that this is not proper way to use ProcessBuilder):
new ProcessBuilder(java, "-version").start().getErrorStream().transferTo(System.out);
Obviously, the above is no help if you wish to determine whether to use Windows console enabled java.exe versus non-console javaw.exe.
I know I can disable Java's use of huge-pages for a process by adding
-XX:-UseLargePages
to the process invocation line.
However, I'd like to prevent every java application from using huge-pages, without me having to discover each process running on the machine.
Disabling THP in RH does not do it. Java still, by default, allocate memory from huge-pages even when THP is disabled.
Try to set this in the environment variable JAVA_TOOL_OPTIONS
See http://www.oracle.com/technetwork/java/javase/envvars-138887.html for details
I checked this with my Eclipse installation. Before starting it I set the variable with set JAVA_TOOL_OPTIONS="-Dfoo=123 -Dbar=456" (using export on the command line or setting it in the environment file will do the same trick on Linux).
Checking the JVM with visualvm shows that the new parameters are considered:
On the console or the corresponding logfile you will most likely see an entry like this:
Picked up JAVA_TOOL_OPTIONS: "-Dfoo=123 -Dbar=456"
In my app i need send http requests via proxy. In terminal i start it by this:
java -Dhttp.proxyPort=**** -Dhttp.proxyHost=***.***.***.*** -jar app.jar
What environment variable i should use for starting on my apps without -D options, like
java -jar app.jar
OS Linux. Java 7.
Thx!
PS already tried JAVA_OPTS, JAVA_OPTIONS, _JAVA_OPTIONS, JAVA_TOOL_OPTIONS...
Java has two separate ways to pass parameters to programs:
Properties, which are typically specified in the command line arguments (as in your first example), loaded from files or manually added by code.
Environment Variables, which are determined by settings in your operating system.
These two concepts are separate; the former doesn't affect the latter and vice versa. As such, you cannot set a property by means of an environment variable.
Other options include loading a .properties file during runtime (assuming your proxy hasn't already been initialized at that point) or putting the full command (-D arguments and all) in a shell script for easier launching.
Nothing is going to work with the standard Java executable. The Java executable does not recognize any environment variables for setting general JVM options.
All those things that you have tried are conventions used by 3rd-party tools, scripts and launchers.
As far as I am aware, the only Java-specific environment variable that the Java executable pays attention to is CLASSPATH, and that is ignored when you run java with the -jar option.
Having said that, there is nothing1 stopping you from:
creating a wrapper script called java and putting it on your search path ahead of the standard java executable, or
creating a shell alias called java.
Such a wrapper or alias could get JVM options from an environment variable, and you could call it anything you wanted to.
1 - ... apart from good sense :-)
I'm trying to invoke a JMX MBean via Jconsole, but the method that I'm calling receive an object that needs to be on jconsole classpath in order to work.
I've tried this and the jconsole does not open (and no error is shown):
jconsole -J-Djava.class.path=%JAVA_HOME%\lib\jconsole.jar;path_to_newjar_\newjar.jar
Take jconsole.jar out of the -J classpath. It's already set in the jconsole launcher.
===== Update =====
Hmmm.... I take back my suggestion. I have a windows batch file I use [which works] which adds a JAR to the classpath. The intent is to add the JMXMP JMX client into jconsole and then launch to the argument specified JMX Service URL. It looks like this:
#echo off
start /B jconsole -J-Djava.class.path=%JAVA_HOME%\lib\jconsole.jar;MY-JAR-PATH\jmx-optional-1.0-b02-SNAPSHOT.jar service:jmx:jmxmp://localhost:%1
If a command like that does not work (i.e. jconsole still will not launch, but does not error out either), then you need to figure out where it is stalling. 2 suggestions for this:
Launch another jconsole and attach to the stalled jconsole by PID, switch to the Threads tab and eyeball what's going on in the main thread.
Or, (since it looks like you're in windows) hit Ctrl-Break and hopefully it will print out a thread dump to the console and you can then eyeball the main thread going-ons there.
Post back if you get anything (or if you don't....)
If you want to have access to both local & remote processes, the above answers are still missing a step.
From the Java 8 oracle docs:
If the JMX agent uses a connector which is not included in the Java platform, you need to add the connector classes to the class path when you run the jconsole command, as follows.
$ jconsole -J-Djava.class.path=JAVA_HOME/lib/jconsole.jar:JAVA_HOME/lib/tools.jar:connector-path
In the command above, connector-path is the directory or the Java archive (Jar) file containing the connector classes that are not included in the JDK, that are to be used by JConsole.
In your case, then, the command would be:
$ jconsole -J-Djava.class.path=%JAVA_HOME%\lib\jconsole.jar;%JAVA_HOME%/lib/tools.jar:path_to_newjar_\newjar.jar
When you leave off the JAVA_HOME/lib/tools.jar, local processes are no longer available.
Solution in Windows is to use quotes on your classpath, for example:
jconsole -J-Djava.class.path="%JAVA_HOME%\lib\jconsole.jar;path_to_newjar_\newjar.jar"
There was a change in Java 1.7 in the way the default Locale is get from the OS. There are methods of restoring the old behaviour e.g. by setting the flag -Dsun.locale.formatasdefault=true when starting a JVM instance.
I would like to set this flag permanently so that I don't have to specify it in command line arguments each time when I start a JVM instance. Is there a file or any other possibility to change the default settings for JVM? Something like the Eclipse.ini file but for the JVM itself?
You can set set environment variable JAVA_TOOL_OPTIONS in your OS. All Java tools (java, javac, ..) will pick this variable up and use it. So you could e.g. use
SET JAVA_TOOL_OPTIONS=-Dsun.locale.formatasdefault=true
I use this to force a specific locale for each JVM.
But this only works if your application is started through the Java tools. If it is e.g. started from a C program that calls the jvm DLL this won't be used.
Edit: I just tested it, and it seems JAVA_TOOLS_OPTIONS is also picked up when the DLLs are started (verified with a Swing application that uses WinRun4J as a launcher)
See: http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/envvars.html