Does GetPrimitiveArrayCritical OpenJDK hotspot never copy? - java-8

in the documentation of GetPrimitiveArrayCritical it says that it may copy the array sometimes. The IBM documentation for their JDK says that it will most likely not copy it if the array size is less then the 1/1000 of the heap size. I looked at the code of the function in OpenJDK 8 and it seams that it never copies it but rather it only sets the isCopy to false.
I checked that in the file
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/872e9c4548bf/src/share/vm/prims/jni.cpp
at line 4250.
Does that mean that if I use openJDK I won't have a problem with the JVM copying the memory?
P.S. I don't care if my code runs on any other JVM.

I double-checked the OpenJDK 8 sources, and yes, it seems that GetPrimtiveArrayCritical indeed never makes a copy. It does not even depend on the garbage collection algorithm. The code in OpenJDK 9 is similar. Whether it is a good idea to rely on this is another question altogether. The similar GetStringCritical method started making copies in OpenJDK 9 in many cases (namely, when a byte array is used as the backing array for the string).

Related

Is Method area still present in Java 8?

Prior to Java 8 we had 5 major runtime data areas:
Method Area
Heap
JVM Stacks
PC registers
Native method stacks
With Java 8, there is no Perm Gen, that means there is no more
“java.lang.OutOfMemoryError: PermGen”
which is great but I also read
Method Area is part of space in the Perm Gen
but I can't seem to find anything which explicitly says Method area is no more in Java 8.
So is Perm Gen along with Method area got removed or only Perm Gen got
removed and Method area is still present in old generation.
Please attach any good source material that you may have seen related to Java 8 Memory Model
Since Method Area is a logical concept described in the specification, every JVM has a Method Area, though that doesn’t imply that it has to be reflected in the implementation code. Likewise, the Java Heap Space is specified as a concept in the specification, to be the storage of all Java objects, therefore all Java objects are stored in the Heap, per definition, regardless of how it is actually implemented.
Unlike the Perm Gen, which contained Java objects and JVM data structures other than Java objects, the memory layout of the HotSpot JVM for Java 8 has a clear separation. The Old Gen still only contains Java objects, whereas the Metaspace only contains JVM specific data and no Java objects. So Java objects formerly stored in the Perm Gen have been moved to the Old Gen. Since the Method Area contains artifacts “such as the run-time constant pool, field and method data, and the code for methods and constructors…”, in other words non-Java-objects (the pool may contain references to heap objects though), it is part of the Metaspace now.
You could now discuss whether the Metaspace is an implementation of Method Area or may contain more than the Method Area, but this has no practical relevance. Practically, the JVM contains code to manage the Metaspace and its contained artifacts and does not need to care whether these artifacts do logically belong to what the specification describes as “Method Area” or not.
Here is the runtime data storage for HotSpot VM In Java 8
Heap
Has got all your objects created using new, including String constant pool
Contains your fields/instance variables
MetaSpace(Method Area)
Contains static data(Class variables and static methods)
Data in here is accessible by Heap, JVM stack
Unlike <=Java7 PermGen which takes JVM process memory which is limited and can't be expanded at runtime. MetaSpace uses native memory
JVM Stack
Current execution of your program.
Contains local variables
It's a thread
Native Stack
Used for native method executions, as Java core language has some native stuff
It's also a thread
PC register/ Instruction Sets
Holds the JVM memory addresses(Not Native address) for each JVM instruction in your stack
Generally each entry in JVM/native stack refers to PC registers for addresses to get actual data from Heap/MetaSpace
Each stack is associated with a PC register

Increase Max Allocated Memory Golang 1.4+

I'm thinking about upgrading to Go 1.4 but am concerned because I no longer know how to change the max amount of memory I can address.
I have been using Go to run some machine learning experiments on a large server, 512GB of main memory, which makes the 128GB limit set using a 37 bit address insufficient.
Previously I would edit malloc.h in the runtime package to change to 38 bit addresses but with the conversion from C to Go of the source I'm having difficulty finding if there is still something as simple to modify.
This commit that changed max memory to 128GB from 16GB shows the kind of change I am talking about https://code.google.com/p/go/source/detail?r=a310cb32c278
So I realized I did not find the file because I am not use to using the Google Code repo explorer. I located what are now 3 malloc.go files and have found the relevant section of code.
https://code.google.com/p/go/source/browse/src/runtime/malloc2.go#122
Honestly I think the update using 1 and 0 booleans and multiplication rather than simple if statements is overly confusing and doesn't convey what is going on as clearly as the header file used to.
Also thank you bamboon I only realized my mistake after reading the mailing list and getting linked to a different repo viewer.

Gradle heap error on uploadArchives

I am trying to upload an archive that's 600MB in size.
I get this error:
Execution failed for task ':uploadArchives'.
> Java heap space
...
...
Caused by: java.lang.OutOfMemoryError: Java heap space
I have tried to set GRADLE_OPTS, JVM_OPTS and MAVEN_OPTS variables, for setting the max. heap size, like for example:
export GRADLE_OPTS=-Xmx1024m
gradle uploadArchives
But I am still getting the same error.
What am I missing here?
Ultimately you always have a finite max of heap to use no matter what platform you are running on. In Windows 32 bit this is around 2gb (not specifically heap but total amount of memory per process). It just happens that Java happens to make the default smaller (presumably so that the programmer can't create programs that have runaway memory allocation without running into this problem and having to examine exactly what they are doing).
So this given there are several approaches you could take to either determine what amount of memory you need or to reduce the amount of memory you are using. One common mistake with garbage collected languages such as Java or C# is to keep around references to objects that you no longer are using, or allocating many objects when you could reuse them instead. As long as objects have a reference to them they will continue to use heap space as the garbage collector will not delete them.
In this case you can use a Java memory profiler to determine what methods in your program are allocating large number of objects and then determine if there is a way to make sure they are no longer referenced, or to not allocate them in the first place. One option which I have used in the past is "JMP" http://www.khelekore.org/jmp/.
If you determine that you are allocating these objects for a reason and you need to keep around references (depending on what you are doing this might be the case), you will just need to increase the max heap size when you start the program. However, once you do the memory profiling and understand how your objects are getting allocated you should have a better idea about how much memory you need.
In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.
Run Java with the command-line option -Xmx, which sets the maximum size of the heap.
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html#nonstandard
The problem was because the actual size of package was a lot higher due to gradle not being able to handle symlinks.
When I manually handled the symlinks, the problem ended.
The JVM heap size can be set in the gradle.properties file, in the root directory of your gradle project. Like this:
org.gradle.jvmargs=-Xms256m -Xmx1024m

performance drop and strange GC behaviour after one hour in jboss 5.0.1GA

We upgraded our software from jboss 4.0.5GA to 5.0.1GA and noticed that after one hour or so (or 90 minutes in some cases) performance drops dramatically.
At the same moment, the garbage collector logs show minor garbage collection times jumping from 0.01s to ~1.5s, with the amount of the heap being cleared each time reducing from ~400MB before to ~300MB after. (see GC viewer graph 1)
We think these are both symptoms of the the same underlying root cause.
jvm settings are:
-server -Xms2048m -Xmx2048m -XX:NewSize=384m -XX:MaxNewSize=384m
-XX:SurvivorRatio=4 -XX:MinHeapFreeRatio=11 -XX:PermSize=80m -verbose:gc
-XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+DisableExplicitGC
-Djava.awt.headless=TRUE -DUseSunHttpHandler=TRUE
-Dsun.net.client.defaultConnectTimeout=25000
-Dsun.net.client.defaultReadTimeout=50000 -Dfile.encoding=UTF-8
-Dvzzv.log.dir=${ercorebatch.log.dir} -Xloggc:${ercorebatch.log.dir}/gc.log
-Duser.language=it -Duser.region=IT -Duser.country=IT -DVFjavaWL=er.core.it
The production environment is T5220 or T2000 hardware, with 32 bit SPARC, running a Solaris 10 virtual machine. jboss 5.0.1.GA, java 1.6.0_17
We set up a test environment consisting of 2 identical boxes, running the same software but one using jboss 4.0.5GA and one using jboss 5.0.1.GA. They are VMWare VMs running on a HP ProLiant DL560 Gen8 with 4 x 2.2GHz Intel Xeon CPU E5-4620 and 64GB RAM. Guest VMs are 4 vCPU, 4096MB RAM, CentOS 6.4.
We found that we could easily reproduce the problem in our environment. The box which was running on 4.0.5 ran fine, but on jboss 5.0.1GA we saw the same strange GC behaviour. Performance can't easily be tested in our environment since we don't have the same amount of load as production.
We don't think it's a memory leak, since after each major GC, the used heap size returns to the same size:
Analysing heap dumps taken pre- and post-apocalypse, we discovered the number of the following objects was different:
org.jboss.virtual.plugins.context.file.FileSystemContext
during the first hour, there are about 8 of them, and after the apocalypse hits, we see between 100 and 800.
Other than that, the heap dumps look quite similar, and the top objects are either java or jboss objects (ie no application classes)
Setting -Djboss.vfs.forceVfsJar=true on our test environment fixed the problem (i.e. the strange GC behaviour disappeared) but when applied in production, both the strange GC pattern and the performance problem remained - although the GC times did not increase so much (to 0.3 seconds rather than 1.5 seconds).
In our test environment, we then deployed the same software in jboss 5.1.0 and found the same behaviour as with 5.0.1.
So the conclusions at this point are that there is something happening in jboss 5.x around the 60 / 90 minute mark which has an impact on both garbage collection and performance.
UPDATE:
We tried upgrading the web services stack to jbossws-native-3.3.1, which fixed the problem in our test environment. However, when deploying to the next test environment (closer to the production environment), the problem was still there (albeit reduced).
UPDATE:
We have resolved this by setting jboss.vfs.cache.TimedPolicyCaching.lifetime to a very large number equivalent to many years.
This feels like a workaround for a bug in jboss. The default cache lifetime is 30 minutes (see org.jboss.util.TimedCachePolicy), and we saw problems after either 60 or 90 minutes.
The VFS cache implementation is CombinedVFSCache and I think it's using a TimedVFSCache underneath.
It seems like a better fix would be to change the cache implementation to a permanent cache, but we've wasted enough time on this problem and our workaround will have to do.
It is hard to determine the root cause of this problem just looking at the Gc graphs. So how does the stacks looks like when this happens? Is there any hyperactive threads? Is there any nasty threads creating a huge pile of objects forcing the garbage collector to work as hell to get rid of them? I think that more analysis must be performed to determine the root cause of the problem.

What kind of memory reclamation algorithm does MRI Ruby 1.8 use?

In other languages you have a number of possibilities usually for memory reclamation:
Mark objects and then remove them
Explicit retain and release
Count references to objects
Internal heap disposition
How does Ruby work?
The garbage collector Ruby 1.8 is actually quite awful. Every 7Mb of allocation it will perform a mark phase from all root objects and try to find which can be reached. Those that cannot be reached will be freed.
However, to find out what objects are reachable, it checks the stack, the registers and the allocated object memory. This allows for some false positives but eases writing C extensions: C extensions don't have to reference and deference, since the stack and so on which C extensions used are automatically scanned.
Furthermore, the state of the object (referenced or not) is kept in the state of each object. This is quite bad for cache behavior and copy-on-write behaviour: a lot of cache lines are touched during this process, and ruby interpreters do not share as much memory as they could if you've got more then one (relevant for server deployment like Ruby on Rails). Therefore, other implementations exists (Ruby Enterprise Edition) which do this in a separate part of the memory to speed GC up.
Also a problem are long linked lists. Since mark-and-sweep uses the stack to do the recursion, a long linked lists segfaults ruby.
The GC does also no compaction and this becomes problematic in the long run.
If you run JRuby however, those problems will disappear while keeping Ruby 1.8 compatibility to some extend.
"conservative mark and sweep"
See this thread which includes Matz' description, which ought to be definitive.
Ruby's GC uses the mark-and-sweep strategy.

Resources