hopefully this is an easy and quick question. I recently developed a CPU intensive java application in Netbeans. It uses A* pathfinding tens of thousands of times per second to solve a tiles matching game. The application is finished, and it runs pretty fast (I've been testing in netbeans the whole time). I've clocked it at 700 attempts per second (each attempt is probably 20 or so pathfinds). When I build the project it creates a jar, and I can run this outside of netbeans. If I use the command line (Windows 7), and use java -jar theFile.jar, I clock it at 1000 attempts per second. This is understandable since the IDE was probably using a bit of cpu power and holding it back (My application is multicored, you can set the number. I usually use 3/4 so it doesnt slow my system too much). Now, the confusing part. Obviously I don't want the user to have to use the command line every time they want to run this application on windows. They should just be able to click the jar. The problem is that when I double click the jar file, the program runs at a sickly 300 attempts per second!!
Why on earth would these three ways of running the exact same program, all else being constant, have such a massive impact on performance? Is my fix to create a script to run the .jar by command line, or do you guys recognize what's going on here? Thanks very much!
Edit: New Information
I made a batch file with the command: java -jar theFile.jar
When this is executed, it runs at the same speed as it would if I ran it in the console (so, 1000 att/sec)
However, I also made an executable with a simple c++ program. The program had just a couple lines, and was System("java -jar theFile.jar"); and return 0;. Unbeleivably, this runs at the speed of double clicking the jar file, about 300att/sec. How bizarre! It could very well be different IDE parameters, but i'm not sure how to check the default system parameters, or how to modify them for this particular jar.
You may be running into the differences between the client and server versions of the HotSpot VM. From this article:
On platforms typically used for client applications, the JDK comes with a VM implementation called the Java HotSpot™ Client VM (client
VM). The client VM is tuned for reducing start-up time and memory
footprint. It can be invoked by using the -client command-line option
when launching an application.
On all platforms, the JDK comes with an implementation of the Java virtual machine called the Java HotSpot Server VM (server VM). The
server VM is designed for maximum program execution speed. It can be
invoked by using the -server command-line option when launching an
application.
I'm guessing that clicking the jar file may be invoking the client VM, unless you set the -server flag. This article provides some more details:
What's the difference between the -client and -server systems?
These two systems are different binaries. They are essentially two
different compilers (JITs)interfacing to the same runtime system. The
client system is optimal for applications which need fast startup
times or small footprints, the server system is optimal for
applications where the overall performance is most important. In
general the client system is better suited for interactive
applications such as GUIs. Some of the other differences include the
compilation policy,heap defaults, and inlining policy.
Where do I get the server and client systems?
Client and server systems are both downloaded with the 32-bit Solaris
and Linux downloads. For 32-bit Windows, if you download the JRE, you
get only the client, you'll need to download the SDK to get both
systems.
For 64-bit, only the server system is included. On Solaris, the 64-bit
JRE is an overlay on top of the 32-bit distribution. However, on Linux
and Windows, it's a completely separate distribution.
I would like java to default to -server. I have a lot of scripts which
I cannot change (or do not want to change). Is there any way to do
this?
Since Java SE 5.0, with the exception of 32-bit Windows, the server VM
will automatically be selected on server-class machines. The
definition of a server-class machine may change from release to
release, so please check the appropriate ergonomics document for the
definition for your release. For 5.0, it's Ergonomics in the 5.0
Java[tm] Virtual Machine.
Should I warm up my loops first so that Hotspot will compile them?
Warming up loops for HotSpot is not necessary. HotSpot contains On
Stack Replacement technology which will compile a running
(interpreted) method and replace it while it is still running in a
loop. No need to waste your applications time warming up seemingly
infinite (or very long running) loops in order to get better
application performance.
Related
I have been studying Operating systems in my free time, but I am confused about how it works with Java & the JVM.
Some questions
when running the java bytecode using a command like java file.class:
I understand that JVM optimize and interpret or perform JIT of the program
How does the JVM get CPU allocation for doing these in a multi-threaded application?
My assumption: In each thread of this application, they all use the same per-process JVM to perform these tasks. (Is this correct?)
What is the role of the operating system with the JVM, what interaction do they have?
(image from Wikipedia)
JVM is just an app
The Java Virtual Machine (JVM) as seen in the OpenJDK project is just another app, usually written in C and C++, sometimes written in Java.
From the point of view of the host operating system, running a JVM is just like running a word-processor, a spreadsheet, or a web browser. All of these apps are large, consuming much memory and spawning threads.
As someone commented, a JVM technically is any software and/or hardware that complies with the official specifications. Indeed, there have been attempts at building hardware chips that knew how to execute Java butecode (see Jazelle and others) but they did not succeed afaik. In practice today, the JVMs we download from Oracle or AdoptOpenJDK or other distributors are simply C/C++ apps that run like any other app on your Mac, BSD, Linux, Windows, AIX, Solaris, or similar machine.
I understand that JVM optimize and interpret or perform JIT of the program
HyperCard from Apple is vintage software similar to Java in that it too executed code internally through an interpreter with a JIT so that repeated runs of the same code blocks would suddenly run faster. HyperCard too was just another app from the point of view of the Mac operating system.
How does the JVM get CPU allocation for doing these in a multi-threaded application?
By scheduling threads on CPU cores like any other app. Word-processors use threads for writing to storage in the background and for re-rendering the document on the background. Web browsers might allocate threads for handling each web page in separate windows/tabs.
In each thread of this application, they all use the same per-process JVM to perform these tasks. (Is this correct?)
Yes, with OpenJDK, you will see one process on your OS for the JVM. All the threads of all the Java apps running within that JVM are housed within that single OS process. However, as someone commented, these are mere implementation details. People are free to implement a JVM as they see fit, in any manner they choose, as long as they comply with the Java specifications.
See the source code
OpenJDK is open-source. So if you are really curious, peruse that source code. Note that you will find areas of code specific to each OS, such as macOS versus Linux versus MS Windows, on each CPU type, such as x86 or ARM or SPARC or such, where the JVM interacts with the host OS.
What are the principles for app deployment in docker?
I see two concepts
Create image per app version
Create app binaries and somehow deploy them to container(utilize i.e. Tomcats hot deploy)
Maybe there are others, I personally like the first, but there must me tremendous amount of data, if you release very often. How would one choose one over the another?
I'd like to know how others deploys their java application so I can make my personal opinion.
Update 2019: See "Docker memory limit causes SLUB unable to allocate with large page cache"
I mentioned in "Docker support in Java 8 — finally!" last May (2019), that new evolutions from Java 10, backported in Java 8, means Docker will report more accurately the memory used.
As mbluke adds in the comments:
The resource issues have been addressed in later versions of Java.
As of Java SE 8u131, and in JDK 9, the JVM is Docker-aware with respect to Docker CPU limits transparently.
Starting with Java JDK 8u131+ and JDK 9, there’s an experimental VM option that allows the JVM ergonomics to read the memory values from CGgroups.
To enable it on, you must explicit set the parameters -XX:+UnlockExperimentalVMOptions and -XX:+UseCGroupMemoryLimitForHeap on the JVM Java 10 has these set by default and there is no need for the flags.
January 2018: original answer
As any trade-off, it depends on your situation/release cycle.
But do consider also Java might be ill-fitted for a docker environment in the first place, depending on its nature.
See "Nobody puts Java in a container"
So we have finished developing our JVM based application, and now package it into a docker image and test it locally on our notebook. All works great, so we deploy 10 instances of that container onto our production cluster. All the sudden the application is throttling and not achieving the same performance as we have seen on our test system. And our test system is even this high-performance system with 64 cores…
What has happened?
In order to allow multiple containers to run isolated side-by-side, we have specified it to be limited to one cpu (or the equivalent ratio in CPU shares). Unfortunately, the JVM will see the overall number of cores on that node (64) and use that value to initialize the number of default threads we have seen earlier. As started 10 instances we end up with:
10 * 64 Jit Compiler Threads
10 * 64 Garbage Collection threads
10 * 64 ….
And our application,being limited in the number of cpu cycles it can use, is mostly dealing with switching between different threads and does cannot get any actual work done.
All the sudden the promise of containers, “Package once, run anywhere’ seem violated…
So to be specific, how to cope with the amount of data generated when you do build image per release? If you build your app everytime on top of tomcat image, the disk space needed for store the images will grow quickly, right?
2 techniques:
multi-stage build to make sure your application does not include anything but what is need at runtime (and not any compilation files). See my answer here;
bind mounts: you could simply copy your wars in a volume mounted by a single Tomcat container.
I had been asked this question in interview, how to start jvm and can we have multiple jvm running on a single system?
Each Java application running uses an independent JVM.
Each JVM is a separate process, and they do not share stacks, heaps. Only common core JVM and native libraries will be shared.
You can have n number of application running on single machine/server box, and so as n number of JVM's.
Launching multiple java processes will create JVM for you.
In all you can have any number of JVM running in your machine, with even different JDK versions.
How to start jvm.
If you have a Java JRE or JDK, then the simple way to start a JVM is to run the java command. For example:
java -jar someapp.jar
starts a JVM that runs the application in the supplied ("executable") JAR file.
Can we have multiple jvm running on a single system?
Yes. Provided you have enough memory.
On a typical OS, each JVM runs as a process. Assuming that the OS allows you to launch multiple processes, you can run multiple JVMs. (This is certainly true for Windows, Linux, MacOSX and other varieties of UNIX on which Java runs.)
The way to start a jvm is by invoking the main, either by invoking a jar using java -jar MyJar or by simply running main class from an IDE.
Yes, Multiple jvm instances can be run on a single machine, they all will have their own memory allocated.
There will be that many jvms as many main programs you run.
I am fairly new to Java or programming in general. On my journeys through the internet to master this language I have come up the saying "write once run anywhere" multiple times.
But I have found many software that requires you to pick the right version for your OS. Sometimes there is only one version available.
Could you explain to me why that is so?
[expanded per the comments]
Java runs on a Virtual Machine, the JVM. In an ideal world this means that the Operating System is abstracted away behind this and you only have to make sure your code works with the JVM which will make it work with the underlying OS. This can already be undone by using the wrong path separators or line endings; it is not an absolute truth.
An application can use many Operating System-specific approaches/libraries/functions/etc that might make it not feasible to restrict yourself to one general codebase. Instead they might want to leverage some advantages provided by a platform and create a separate application with it.
The statement should probably be somewhere along the lines of "Write once in a general fashion, run anywhere" but that's not as snappy.
This statement is often linked to Java but there are also other languages that incorporate this: weblanguages like Javascript and HTML will run on any browser because the browser itself forms the abstraction between the language and the underlying OS.
Other languages don't have this (entirely?) since they work differently: C# will use the underlying .NET framework which as it is only exists for Windows. There exists a cross platform variant (Mono) but it would be an overstatement to consider C# truly cross platform.
The Java program or source code is compiled to generate "bytecodes" ( an intermediate binary format). Second, the bytecodes is executed by an interpreter which is part of the Java Virtual Machine (JVM).
"Write Once, Run Everywhere" refers to the fact that an application written is Java can be run on any hardware which has the Java Virtual Machine (JVM), and that the JVM is now licensed to hundreds of operating systems vendors systems including Microsoft for Windows.
Well, some stuff is really cross-platform (most of standard Java library), while some other stuff may need right version for the OS. Generally, this applies to software that uses dynamic libraries, that aren't written in Java. In this case, versions for different OSes are packed with libraries for this OS.
In case there's version only for one OS - it could be because required libraries don't exists for other OSes or developer didn't port it. There is still possibility that it's actually cross-platform, but developer tested it only under one OS.
Your question is more based on platform dependency/independency.
Java is a programming language which is platform independent which means the code which you write will produce the same output on all machines running Windows, Linus, Unix, etc... without any changes to the code. To run a Java program you need to have JVM (Java Virtual Machine) installed. Now what does JVM do.? Well, it translates your code into Machine code which the Operating System could understand. Therefore JVM is platform dependent since every OS has a different Machine code.
So, basically you write a Java Program only once and can be used/run everywhere.
you can write source code in one platform and run it any where.some times you can encounter problem if a new java version is available but still current version runs the code.
It seems to be a simple question, but I wasn't able to find a meaningful answer, only a lot of speculations.
Also, if an answer is yes, which JVM would it be, Oracle's or again something patched by Microsoft?
Specifically: I have a Java desktop application, running on JRE 7, would it run on WinRT?
I mean, can I install JRE 7 on WinRT? Would it run without problems?
Yes and no.
It would certainly be possible to implement a Java Virtual Machine, or at least a substantial portion of one, using the Windows Runtime APIs and the portions of the Windows API that are usable from a Windows Store app. However, such a JVM would need to be an interpreting JVM, not a JIT compiling JVM. JIT compilation requires the ability to change memory protection (to allow execution of generated code), but the APIs to change memory protection (VirtualProtect and friends) are not callable from user code in a Windows Store app.
So, could you implement an interpreting JVM usable in a Windows Store app? Probably. Whether or not it would be possible to implement a JVM that performs well enough to be usable is another matter altogether, though.