39

We have a PHP webapp that calls a Java binary to produce a PDF report (with JasperReports). The Java binary outputs the PDF to standard output and exits; the PHP then sends the PDF to browser. This Java command lasts about 3 to 6 seconds, and I think when it lasts 6 second it's because the GC kicks in. I would like to disable the GC because anyway when the command exits all memory is returned.

I would like to know how to disable it for Java 1.4.2 and for Java 1.6.0 because we are currently testing both JVM to see which performs faster..

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Nelson
  • 49,283
  • 8
  • 68
  • 81
  • 7
    Just a hint to an other approach (since process starting takes time, too): http://github.com/hudora/pyJasper contains a (java)server which runs jasperreports on requests, without the process startup/shutdown overhead. – ZeissS May 28 '10 at 08:16
  • Related for specific objects: http://stackoverflow.com/questions/1329926/how-to-prevent-an-object-from-getting-garbage-collected – Ciro Santilli OurBigBook.com Mar 04 '15 at 08:08

10 Answers10

38

It sounds like you are trying to save time, but going about it the wrong way. The time saved in disabling garbage collection would be trivial (for a single task) compared to the time taken to launch and shutdown the java process. You might want to consider having a java process launch that you can ask multiple times to do the work you require if run-time performance is your goal.

Paul Jowett
  • 6,513
  • 2
  • 24
  • 19
  • Yes, this is good approach although more work to do, I would have to code a kind of daemon that would listen on sockets and so on.. besides this "daemon" would have to be restarted once in X days.. cause java leaks memory in the long run (from my experience).. – Nelson May 28 '10 at 08:20
  • @Nelson Consider seeing if you can use something like Mule to host your Java processes and let that handle all of the communications for you. The idea being that you just need to embed your JasperReports as a service that the ESB can host and route requests to as necessary. Mule: http://www.mulesoft.com/mule-esb-open-source-esb – Trevor Tippins May 28 '10 at 08:28
  • 4
    @Nelson Java doesn't leak memory per se. We have java deamons running for months, only restarted for application updates or system downtimes. If your Java programs are leaking, try to use a profiler. There are other options than open the socket yourself. There is ActiveMQ/JMS, JMX, or you could create a webservice for it, maybe jetty would be interesting. – Hardcoded May 28 '10 at 08:46
33

There is no way to disable garbage collection entirely. Garbage collection is only run when the JVM runs out of space, so you could give the program more memory. Add these command line options to the Java command

-Xmx256M -Xms256M

This gives the program 256Mb of ram (the default is 64Mb). Garbage collection will not take 3 seconds for a default size JVM though, so you might want to investigate more closely what the program is doing. Yourkit profiler is very useful for figuring out what is taking a long time.

Kevin Panko
  • 8,356
  • 19
  • 50
  • 61
Ceilingfish
  • 5,397
  • 4
  • 44
  • 71
32

GC only kicks in when JVM is short on memory, so you either GC or die. Try turning on verbose GC and see if it actually takes significant amount of time.

java -verbose:gc
unbeli
  • 29,501
  • 5
  • 55
  • 57
  • 1
    Umm, then maybe I could use a commandline switch to give it more memory and so increase the chance the GC does not kicks in.. – Nelson May 28 '10 at 08:00
  • 2
    Yes, you will know if you need to do that after analyzing the output of verbose:gc. That's the first step. – unbeli May 28 '10 at 08:01
  • 8
    +1 for "test, don't guess". The time diff could be something completely unrelated, like I/O contention or some CPU heavy process kicking in. – gustafc May 28 '10 at 08:08
17

Java 11 comes with an no-op garbage collector.

It can be enabled by the -XX:+UseEpsilonGC option at JVM start.

According to the JEP decription one of its goals is to make certain short-lived jobs more efficient, what might be you use case:

Extremely short lived jobs. A short-lived job might rely on exiting quickly to free the resources (e.g. heap memory). In this case, accepting the GC cycle to futilely clean up the heap is a waste of time, because the heap would be freed on exit anyway. Note that the GC cycle might take a while, because it would depend on the amount of live data in the heap, which can be a lot.

aventurin
  • 2,056
  • 4
  • 26
  • 30
5

Java 11 gives you the binary option to either have Java GC on, or have Java GC turned off. To turn off Java GC you use the Epsilon Garbage Collector which must be turned off on the command line. On Java 11, use the following two JVM arguments:

-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

Without the UnlockExperimentalVMOptions argument, the JVM will fail to start, so make sure it's included.

Can't Stop Java GC

Unfortunately, if you're not using Epsilon GC, there is no way to disable, stop or prevent garbage collection from happening. Just like not being able to trigger GC, you can't stop Java GC either. The algorithms are non-deterministic. Only the JVM can control when they occur.

Cameron McKenzie
  • 3,684
  • 32
  • 28
2

You can use the -Xmx option to set the maximum heap size; using a larger heap should prevent the VM from runnning out of memory and, thereby, requiring garbage collection so soon.

Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • 2
    Just setting -Xmx won't make any difference. You actually need to set -Xms as well since you want to control the initial heap size. – Stephen C May 28 '10 at 08:14
1

Are you sure that it is garbage collection causing the slowdown? Have you run java with -verbose:gc to see what is happening?

You cannot disable garbage collection on the JVM. You could however look at tuning the garbage collector for better performance.

Mark
  • 28,783
  • 8
  • 63
  • 92
0

Contrary to what everyone else has said, there is a way to suspend GC, though it's very convoluted.

If you call a native function via JNI, in between the native code calling GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical, GC is suspended. It has to do this because it is the mechanism used for sharing memory between Java and native code, and GC may move objects around in memory.

So to utilise this you'd need to create a JNI function which calls the former, then polls a flag written to that critical array (which could just be a byte[1]) waiting till it sees the flag before calling the latter. When the Java code wishes to suspend GC it would call the JNI method and when it wishes to resume GC, set the aforementioned flag (I believe reads/writes to the critical array are volatile, so the native code would see the flag immediately).

Now I'm not saying this is a good idea, and certainly not the correct solution to the OP's problem. But if you absolutely had to temporarily suspend GC for some reason (perhaps you wish to manipulate raw memory via sun.misc.Unsafe and needed to ensure objects were not moved about by GC whilst doing so), that's how you could achieve it.

barneypitt
  • 979
  • 9
  • 11
-2

As everyone as said you can't disable GC in the JVM, which makes sense right, because if you could there'd be memory leaks due to java not having an explicit way for the developer to delete the heap data.

Do you have access to the source of this java binary? If so it might be worth analysing it and seeing if there's any bottle-necks which could be better written to cut down on GC activity. This could be done with most java profilers, like JProbe for example.

display101
  • 2,035
  • 1
  • 14
  • 10
  • the java binary is very simple, it just retrieve commandline paraemeters and make calls into jasperreport functions to create the report, which is passed to the System.out outputstream where the PHP read it through 'passthrough' function. So the the time is spent on Jasperreport proccessing the report, thats how I wanted a java general speedup. – Nelson May 28 '10 at 08:28
  • It looks like controlling the JVM GC settings is your only avenue here then. – display101 May 28 '10 at 08:39
-4

To avoid garbage collector release a variable or property from any object, you must set this property (released by gc) as static in your class it was my solution.

Example:

private static String myProperty;