I understand there's -Xloggc option exists for outputting GC output to separate file. But it doesn't work for me. I've 16 java processes with same main running on one machine so I can't really hardcode file path. Ideally I want to specify only directory where separate pid specific files are created. Is that possible? Note I don't want GC output mixed with stdout and hence a need for separate file.
Version : SunJDK 1.5_13
Can you change the loggc directory with
-Xloggc:/path/`date +%Y%M%d%H%m%S`.gc.log
Couldn't you mix standard out and GC and then grep out what you want? There should be much coming out of standard out, or at least not much that you couldn't redirect elsewhere if you are using a logging framework.
Related
I am wondering, how does JPS tool get the name of the main class it is executed within jvm process. It is
jps -l
123 package.MainClass
456 /path/example.jar
I am talking specifically about Linux (I am not interested in Windows, and I have no Win machine to experiment on).
I could think of 2 ways
Connecting to the JVM in question which in turn tells it
From /proc file system
Regarding the first alternative, is it using local JMX connection? Still, it must go to /proc for the pids.
There is PID, so it must ask OS anyway
jps lists also itself
Regarding the second alternative, I feel this could be the correct one, because
On the command line, there is either -jar or MainClass
/proc knows wery well the PID
Before jps starts doind something, it has own folder in /proc
But, I am facing little problem here. When java command is very long (e.g. there is extremely long -classpath parameter), the information about the command line does not fit into space reserved for it in /proc. My system has 4kB for it, and what I learned elsewhere, this is hardwired in OS code (changing it requires kernel compilation). However, even in this case jps is still able to get that main class somewhere. How?
I need to find quicker way to get JVM process than calling jps. When system is quite loaded (e.g. when number of JVMs start), jps got stuck for several seconds (I have seen it waiting for ~30s).
jps scans through /tmp/hsperfdata_<username>/<pid> files that contain monitors and counters of running JVMs. The monitor named sun.rt.javaCommand contains the string you are looking for.
To find out the format of PerfData file you'll have to look into JDK source code.
Any way to hook on stdout of JVM currently running process or redirect stdout of JVM process to non file location?
I need verbose:gc output of JVM for my application, currently i can see this output in console but unable to store it in database or process it by any means, it invisible to running java application.
System.err
System.out
Both are wrappers over natives, internal JVM output not passes here.
Both can't see this output (ever if redirected or set to null, gc output shows in console).
Writing verbose:gc to file and then reading file not valid option due performance reasons and filesystem locks, checking hotspot sources not given any way to redirect output to nonfile location via JVM launch flags.
Also i was unable to get Process object of running JVM, there are no methods for this, also i was unable to find native that expose Process object, soo still no valid way to read this data.
Any clues about howto read verbose:gc in runtime?
Writing verbose:gc to file and then reading file not valid option due performance reasons and filesystem locks,
The cost of doing this is trivial compared to the cost of actually GCing. Unless you have a system which should never GC normally, I wouldn't worry about it. If you concern is that you can't read the file due to windows locks, you may have a problem (or you could use an OS like Linux which doesn't do this)
You should note that the GC output to a file is buffered, so it is not real time (but close enough for most use cases)
Reading the output programmatically is very difficult esp as it is written by a multi-threaded GC i.e. you get strange re-ordering of information.
I would consider getting the output of jstat which is designed to be read by a program though doesn't get as much detail.
You can get information GC pause information via JMX. It is not as full as GC logs, but will safe you from parsing. SJK tool is a CLI tool which could track GC events of JVM running processes. You could use it or use its code to build customized solution.
jstat is another option, but it exposes less information compared to JMX and its formatting rather misleading in case of CMS collector.
Problematically using PerfCounter API is third option (jstat is using this internally). See sun.management.counter.perf.PerfInstrumentation class for details.
Ok, so I have a couple of Java programs that I'm running using a chron job on a linux server. These jobs run every ten minutes or so, take literally two minutes to run, and then exit. I need to add a way for the programs to detect, when they start up, if there is already an instance of themselves running, and if so to exit without going any further. I'm really not sure of the best way to handle this though and am hoping someone can offer some advice.
One approach I've considered is to run a command line argument from the java code that does some sort of PS command and looks through those to see if it's running. This seems pretty finicky and complex though for something so small. Plus, I'm not all that knowledgeable with linux and am not even sure the best way to do that. If anyone has some better thoughts, please let me know. Or if that is the best way, if you could provide the linux commands I'd need I'd appreciate it. Thanks.
If you have a writable /tmp directory you can use a lockfile.
When your Java program starts up, check for a file with a name unique to your application (e.g. "my-lock-file.lock") in the /tmp directory. If none exists, create one, and remove it when you're done. If one exists, just exit.
You can check the existence of a file with the .exists() method of the java.io.File class.
If your code needs to be portable, you can use System.getProperty("java.io.tmpdir")); to get an appropriate temporary directory for the platform your code is running on.
You could look at JMX and the Attach API to query for running JVMs.
Or, as Andrew logvinov mentioned, by using a lock file.
If you are using Java WebStart, there's already native support for this.
Many programs solve this by creating a temporary file that points to their PID (often referred to as a "lock" file). The filename should encode all relevant information to distinguish this process from other processes that could legitimately run in parallel.
For example, if the process is bound to a user, it should contain the user name. If the process is bound to a machine, it should (also) contain the hostname (if you put it in machine-bound temp. directory, this is debatable. If you put it in a home directory, think of the case of multiple machines sharing a home via NFS).
The location of these files is typically /tmp. This is a great location, as /tmp is typically wiped during system boot, so no orphan files are left in case of a system crash. Another solution employed by some programs is to put the lock file in the user settings directory, if it is related to the settings. E.g. mozilla thunderbird has a file called /home/<username>/.thunderbird/<profilename>.default/lock.
The file should contain the PID of the process. The idea is simple: If the file contains the PID, it is easy to check whether this process is indeed still running. So if the process crashes, the file gets orphaned. The new process instance will check the PID in the file, see that it is not running any more, and ignore the file (overwrite).
Putting it all together, you could create a file like this:
/tmp/myawesomeservice-username-hostname-lock
With the content:
12345
this really silly question probably, as no one else seems to be having this problem. In the Jetty documentation it says jar -jar start.jar starts Jetty, and it does. But when I close my SSH console, obviously it dies.
How do I run it PROPERLY?
Is this for running on a production machine that will actually serve up an application running under Jetty? I assume this is the case, since you're asking about starting it properly.
If so, you need a proper process supervision system, such as runit, daemontools, monit, upstart, systemd, or good ol' SysV init.d (as mentioned w/ a gist). Which to use depends on your preferences, business needs, and often, your underlying operating system.
I use and prefer runit. It is built on solid principles (daemontools), and for my preferred distribution (Debian and Ubuntu) it is nicely packaged by the author himself.
Despite being recommended in other answers, and mentioned in comments, starting a long running process in screen/tmux, or via nohup is sub-optimal. You don't have any real control over the process. It won't be restarted if it dies. You have to manually find its PID and otherwise manually manage the service. You have to do more manual work to get the log output (redirection, sending to some random file, etc). You cannot reliably make it depend on other processes, or have other processes depend on it. Decent process supervision systems provide all this functionality for you by default.
If your goal is something else entirely, then please update the question to be more specific about your use case.
java -jar start.jar &
(to run in the background) should also work, though logging won't be transmuted as nice as w/nohup.
This is because killing the shell that started a process (e.g. by logging out) will kill process to unless they're background processes. Screen works since as well since it runs in the background, and screen effectively keeps your session running while you attach/detach.
One way is to use nohup
nohup java -jar start.jar
This has the advantage of writing stdout and stderr to a file
Another way would be to use screen
If you're on a *nix system, the best solution is may be using a script in /etc/init.d (or whatever your system's equivalent is). There's one at https://gist.github.com/404672.
Otherwise, using nohup or screen from the command-line will at least have the process not die when you log out. So will putting the process in the background with &.
I've noticed that when I start Netbeans it shows up in the task manager as netbeans.exe as all my own Java applications show up as java.exe or javaw.exe.
How can I change that so my process names shows up as myapp.exe?
The process name is the name of the JVM. So if you rename the jvm you have an other process name. There are some tools which can do that for you. For example Launch4J
IMO the best option is to choose one of the many open source launchers. They all provide a nicer deployment container than java.exe and a batch file.
I've compiled a list of them after a brief search on google (in no particular order and may not be exhaustive):
NSIS
Janel (dead link)
JSmooth
Launch4J
WinRun4J
(full disclosure: i work on winrun4j)
Not easily. The easiest way (but not nice!) would be to simply copy the java.exe (only 68k on my system, so perhaps practical!)
If you're worried about identifying which java process is which (e.g. is one consuming memory/CPU etc.), use the standard tool jps to identify the Java processes
Netbeans and Eclipse both ship with an .exe file that in turns launches a JVM. The exe itaself probably does nothing after launching the VM. You see the NetBeans javaw.exe in the Task Manager also, I suspect.
So you'll need to write a native exe (using some windows tool) that does a similar thing.
Just answered this a second ago here: Get JVM to grow memory demand as needed up to size of VM limit?
It's actually a lot easier than folks are saying (but you do have to have a c/c++ compiler handy).
There are mainly 2 approaches: one is as already described: using tools like Launch4j, WinRun4J to create native Windows launchers.
Another approach that seems better is to use Apache Procrun to wrap the java application as a Windows service. During the install service process, we can give the process an meaningful name such as OurApp.exe.
All we need do is rename prunsrv.exe to OurApp.exe and replace every occurrence of prunsrv.exe in our install|start|stop|uninstall service scripts to MyApp.exe.
See more from Using Apache Procrun to Rename Process Name of a Java Program in Windows