How to increase the Java stack size?
Hmm... it works for me and with far less than 999MB of stack:
> java -Xss4m Test
0
(Windows JDK 7, build 17.0-b05 client VM, and Linux JDK 6 - same version information as you posted)
How to increase stack size to allow more recursion?
Your error is indeed a StackOverflow caused by too much recursion, but Processing covers that up with the strange error you're seeing. Documentation on that bug is here.
You can increase the Java stack size to increase the limit of recursive calls. Info can be found here, but the gist is that you have to pass the -Xss setting into Java at runtime.
However, that setting requires that you run your sketch as a Java application. This is possible, but it involves exporting your sketch as a jar, then running the jar via the command prompt, or switching to eclipse. That's a lot more work than simply hitting the run button in Processing- and any users you send your jar would have to do the same.
Instead, you should probably refactor your algorithm to eliminate the excessive recursion.
What is the default stack size, can it grow, how does it work with garbage collection?
How much a stack can grow?
You can use a VM option named ss
to adjust the maximum stack size. A VM option is usually passed using -X{option}. So you can use java -Xss1M
to set the maximum of stack size to 1M.
Each thread has at least one stack. Some Java Virtual Machines (JVM) put Java stack (Java method calls) and native stack (Native method calls in VM) into one stack, and perform stack unwinding using a "Managed to Native Frame", known as M2nFrame. Some JVMs keep two stacks separately. The Xss
set the size of the Java Stack in most cases.
For many JVMs, they put different default values for stack size on different platforms.
Can we limit this growth?
When a method call occurs, a new stack frame will be created on the stack of that thread. The stack will contain local variables, parameters, return address, etc. In Java, you can never put an object on stack, only object reference can be stored on stack. Since array is also an object in Java, arrays are also not stored on stack. So, if you reduce the amount of your local primitive variables, parameters by grouping them into objects, you can reduce the space on stack. Actually, the fact that we cannot explicitly put objects on Java stack affects the performance some time (cache miss).
Does stack has some default minimum value or default maximum value?
As I said before, different VMs are different, and may change over versions. See here.
How does garbage collection work on stack?
Garbage collections in Java is a hot topic. Garbage collection aims to collect unreachable objects in the heap. So that needs a definition of 'reachable.' Everything on the stack constitutes part of the root set references in GC. Everything that is reachable from every stack of every thread should be considered as live. There are some other root set references, like Thread objects and some class objects.
This is only a very vague use of stack on GC. Currently most JVMs are using a generational GC. This article gives brief introduction about Java GC. And recently I read a very good article talking about the GC on .NET platform. The GC on Oracle JVM is quite similar so I think that might also help you.
What sets the stack size?
the JVM and yes you can pass parms to change the stack size. This question/answer is somewhat close to your question. How to increase the Java stack size?
How to fine tune JVM configurations to reduce the max thread stack size?
Yes, you can do that. Basically, you can configure the max Stack size of your thread in your application.
For this, you can use the option named ss
to adjust the maximum stack size. A VM option is usually passed using -X{option}
. So you can use java -Xss1M
to set the maximum of stack size to 1M
.
One more example is java -Xss1048576
, this sets the max thread size to approximately 1 MB
Checkout the two below blogs also for more info and other flags.
-> https://www.baeldung.com/jvm-configure-stack-sizes
-> https://docs.gigaspaces.com/latest/production/production-jvm-tuning.html
Increase heap size in Java
You can increase to 2GB
on a 32
bit system. If you're on a 64 bit system you can go higher. No need to worry if you've chosen incorrectly, if you ask for 5g on a 32 bit system java will complain about an invalid value and quit.
As others have posted, use the cmd-line flags - e.g.
java -Xmx6g myprogram
You can get a full list (or a nearly full list, anyway) by typing java -X.
Java stack overflow error - how to increase the stack size in Eclipse?
Open the Run Configuration for your application (Run/Run Configurations..., then look for the applications entry in 'Java application').
The arguments tab has a text box Vm arguments, enter -Xss1m
(or a bigger parameter for the maximum stack size). The default value is 512 kByte (SUN JDK 1.5 - don't know if it varies between vendors and versions).
Update a java thread's stack size at runtime
The stack size dynamcally updates itself as it is used so you never need to so this.
What you can set is the maximum size it can be with -Xss
This is the virtual memory size used and you can make it as large as you like on 64-bit JVMs. The actual memory used is based on the amount of memory you use. ;)
EDIT: The important distinction is that the maximum size is reserved as virtual memory (so is the heap btw). i.e. the address space is reserved, which is also why it cannot be extended. In 32-bit systems you have limited address space and this can still be a problem. But in 64-bit systems, you usually have up to 256 TB of virtual memory (a processor limitation) so virtual memory is cheap. The actual memory is allocated in pages (typically 4 KB) and they are only allocated when used. This is why the memory of a Java application appears to grow over time even though the maximum heap size is allocated on startup. The same thing happens with thread stacks. Only the pages actually touched are allocated.
How to extend stack size without access to JVM settings?
To sum up the comments, you can create a new Thread and specify a stack size, though the docs say that the effects are highly platform dependent (works on my computer at least). See more here: https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Thread.html#%3Cinit%3E(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String,long)
Example:
public static void main(String[] args)
{
Thread thread1 = new Thread(null, null, "qwer", 1000000) {
public void run() {
System.out.println(countDepth());
}
};
thread1.start();
}
public static int countDepth() {
try {return 1+countDepth();}
catch(StackOverflowError err) { return 0; }
}
(change the stacksize and you will see much higher recursion depths)
JVM stack size specifications
Question, what does 1 MB stack size states in JVM as I have no idea what size a stack frame of?
A 1 MB default thread stack size means that every thread has 1MB (1048576 bytes) of stack space ... by default. The exception is if your code creates a thread using one of the Thread
constructors where you can provide a stack size argument.
The size of a stack frame depends on the method being called. It needs to hold the method's parameters and local variables, so the frame size depends on their size. Each frame also needs (I think) two extra words to hold a saved frame pointer and a saved return address.
Note that in a recursive algorithm, you can have more than one stack frame for one "level of recursion". For writeObject
(in Java 8), the algorithm used is recursive, and there are typically 4 frames per level of the data structure being serialized:
writeObject0
writeOrdinaryObject
writeSerialData
defaultWriteFields
writeObject0
etcetera
The actual frame sizes will be platform dependent due to differences in compilers, and changes in the implementation of ObjectInputStream / ObjectOutputStream. You would better off trying to (roughly) measure the required stackspace rather than trying to predict frame sizes from first principles.
One more question, does every thread has 3000k stack size if I put a JVM option of -Xss3000k ?
Yes ... with the exception that I have described above.
One possible solution to your dilemma is create a special thread with an huge stack that you use for serialization. A similar thread with a huge stack will be required for deserialization. For the rest of the threads, the default stack size should be fine.
Other possible solutions:
Implement
writeReplace
andreadResolve
methods to flatten the parent structure of your epc objects into an array so that you don't get deep recursion. (Obviously, the flattening / unflattening needs to be done non-recursively.)Do the same flattening before you call
writeObject
, etcetera.Use a different serialization mechanism, or possible a custom one.
Related Topics
Socket Using in a Swing Applet
Ways to Iterate Over a List in Java
Avoid Synchronized(This) in Java
Display Java.Util.Date in a Specific Format
Replace a Character At a Specific Index in a String
Why Does Java Have Transient Fields
Where Does the @Transactional Annotation Belong
Why Is the Java Date API (Java.Util.Date, .Calendar) Such a Mess
How to Override Equals Method in Java
Java: Convert List≪String≫ to a Join()D String
How to Add to List≪? Extends Number≫ Data Structures
Add Leading Zeroes to Number in Java
Is There an Advantage to Use a Synchronized Method Instead of a Synchronized Block
What's the Best Way to Check If a String Represents an Integer in Java