I know this question has been answered already via numerous methods:
Set maximum stack size (-Xss20m)
Avoid the test what so ever - if you need a bigger recursion the problem is within the program.
Those methods are great, but I know there is a problem in my code, and I want to specifically limit (to a small number e.g. 5) the recursion depth, to test whether this is the problem.
Is there a method, like the sys.setrecursionlimit in python?
The least invasive "Manual" way to do this (also the most hacky) is probably to create a static variable in your class that is having the recursion issue. When you enter the recursive method use it to count the recursion depth (by adding or subtracting) and when you exit, reverse what you did upon entry.
This isn't great but it is a lot better than trying to set a stack depth (Nearly any system call in java will blow through 5 levels of stack without even blinking).
If you don't use a static you may end up having to pass your stack depth variable through quite a few classes, it's very invasive to the rest of your code.
As an alternative I suggest you let it fail "normally" and throw the exception then meditate upon the stack trace for a while--they are really informative and will probably lead you to the source of your problem more quickly than anything else.
static int maxDepth = 5;
public void recursiveMethod() {
if(maxDepth-- == 0)
throw new IllegalStateException("Stack Overflow");
recursiveMethod();
maxDepth++;
}
Create this class:
public class RecursionLimiter {
public static int maxLevel = 10;
public static void emerge() {
if (maxLevel == 0)
return;
try {
throw new IllegalStateException("Too deep, emerging");
} catch (IllegalStateException e) {
if (e.getStackTrace().length > maxLevel + 1)
throw e;
}
}
}
Then import static and insert emerge() call into the beginning of any method in your code that can be deeply recursive. You can adjust maximum allowed recursion level via the maxLevel variable. The emerge() procedure will interrupt execution on a level greater than the value of that variable. You can switch off this behaviour by setting maxLevel to 0. This solution is thread-safe because it doesn't use any counter at all.
Related
I am trying to find the square of a number using the scanner method but keep getting a
stackflow error. I am new to programming will be glad if someone helps me out.
My code is as below
import java.util.Scanner;
interface Number {
int findSqr(int i); // Returns the square of n
}
//a class A which implements the interface Number.
class A implements Number {
public int findSqr(int i) {
return findSqr(i);
}
}
public class Question5_1{
public static void main (String[] args){
A a = new A(); // an object of class A
// Reading a number from the keyboard
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
System.out.print(a.findSqr(i));
}
}
Fix the line which invokes the function recursively return findSqr(i) with return i * i as follows --
public int findSqr(int i) {
return i * i;
}
What you did there is an infinite recursion. The bit where it says
public int findScr(int i) {
return findSqr(i)
}
essentially calls the very same method an infinite number of times in the return statement.
What happens is, that you execute the method, and it tries to return an integer. What you wrote though is a return statement that "returns" another call of the same method, so it gets executed again. Then the whole thing starts over again, so you get a StackOverflow.
Since there is no other code present, I have no idea what you are actually trying to do, but the return findSqr(i) line is what causes the problem.
Initially, recursion may be a rather complicated subject to really wrap you head around, I suggest you either avoid it for now (although it enables you to solve many problems in a really elegant way) or try to understand it a bit better maybe. I'd suggest the Wikipedia article about recursion, although it gets complicated quite fast, or any other tutorial on it, just look it up on Google.
I've called upon what I've learned so far and still can't fix this so decided to come here.
A BasicBlock object is referenced by an integer and holds references to the 'addresses' of more blocks in a list. I want to obtain the addresses that they hold reference to and i thought to do this recursively. It is possible for one BasicBlock to hold reference to 0 or more other blocks.
The below recursive function getFunctionReferences keeps returning a stack overflow error, yet manages to work sometimes.
Map<Integer,BasicBlock> blockList blockList = new TreeMap<Integer,BasicBlock>();
public HashSet<Integer> getAssociatedAddresses(int function) {
HashSet<Integer> blockAddresses = new HashSet<Integer>();
getFunctionReferences(this.blockList.get(function),blockAddresses);
return blockAddresses;
}
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
blockAddresses.add(x);
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
I know that I am doing something wrong with this call, especially as there is no base case. But I don't know how to deal with recursion when it is in a loop like this....nor do I know a suitable base case.
Help massively appreciated.
Thanks
If you have cycles (for example block 1 references block 2 which references block 3 which references block 1), you'll get infinite recursion leading to StackOverflowError.
To avoid that, you can take advantage of the HashSet of visited blocks which you maintain. You can simply check if a block was already visited and avoid making another recursive call if it was:
private void getFunctionReferences(BasicBlock block, HashSet<Integer> blockAddresses){
for (int x : block.getAddressReferenceList()) {
if (blockAddresses.add(x)) { // only make a recursive call if x wasn't already
// in the Set
getFunctionReferences(this.blockList.get(x), blockAddresses);
}
}
}
You give a grid (4x4 here). you need to find out the total no of unique paths from (0,0) to (4,4). main() call a function pathify for this. It finds the possible "next steps" and calls it again. When (4,4) is reached noOfPaths++; is supposed to execute. This doesn't happen and I can't find the problem.
import java.util.ArrayList;
public class NoOfPaths {
static int xRows = 4;
static int yColumns = 4;
static int noOfPaths = 0;
/*A robot is located in the upper-left corner of a 4×4 grid.
* The robot can move either up, down, left, or right,
* but cannot go to the same location twice.
* The robot is trying to reach the lower-right corner of the grid.
* Your task is to find out the number of unique ways to reach the destination.
**/
static ArrayList validNeighbours (int x,int y, ArrayList visited) {
ArrayList valid = new ArrayList();
if((x+1 <= xRows) && !visited.contains(((x+1)*10)+y) ) {
valid.add(((x+1)*10)+y);
}
if((x-1 >= 0) && !visited.contains(((x-1)*10)+y) ) {
valid.add(((x-1)*10)+y);
}
if((y+1 <= yColumns) && !visited.contains(x*10+y+1) ) {
valid.add(x*10+y+1);
}
if((y-1 >= 0) && !visited.contains(x*10+y-1) ) {
valid.add(x*10+y-1);
}
return valid;
}
static void pathify(int x,int y, ArrayList alreadyVisited) {
if(x == xRows && y == yColumns) {
noOfPaths++;
} else {
alreadyVisited.add(x*10+y);
ArrayList callAgain = new ArrayList();
callAgain = validNeighbours(x,y,alreadyVisited);
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
}
}
public static void main(String[] args) {
ArrayList alreadyVisited = new ArrayList();
pathify(0, 0, alreadyVisited);
System.out.println(noOfPaths);
}
}
The error is in how you're handling alreadyVisited. The first time pathify is called, this list will contain only the initial square (0,0), which is fine. Here's the important part of your code:
for (int t=0,temp; t<callAgain.size(); t++) {
temp=(int) callAgain.get(t);
pathify(temp/10, temp%10, alreadyVisited);
}
You've found the neighbors of the initial cell. Your code will pick the first neighbor; then it will find paths starting with that neighbor, and the recursive calls to pathify will add cells to alreadyVisited.
Now, after all the recursive calls come back, you're ready to find cells starting with the second neighbor of the initial cell. But you have a problem: alreadyVisited still has all the cells it's collected from the paths it found starting with the second neighbor. So you won't find all possible paths starting with the second neighbor; you won't find any path that includes any cell in any path you've previously found. This isn't what you want, since you only want to avoid visiting the same cell in each path--you don't want to avoid visiting the same cell in all your previous paths. (I simplified this a little bit. In reality, the problem will start occurring deeper down the recursive stack, and you won't even find all the paths beginning with the first neighbor.)
When implementing a recursive algorithm, I've found that it's generally a bad idea to keep an intermediate data structure that is shared by recursive invocations that will be modified by those invocations. In this case, that's the list alreadyVisited. The problem is that when an invocation deeper down the stack modifies the structure, this affects invocations further up, because they will see the modifications after the deeper invocations return, which is basically data they need changing underneath them. (I'm not talking about a collection that is used to hold a list of results, if the list is basically write-only.) The way to avoid it here is that instead of adding to alreadyVisited, you could create a clone of this list and then add to it. That way, a deeper invocation can be sure that it's not impacting the shallower invocations by changing their data. That is, instead of
alreadyVisited.add(x*10+y);
write
alreadyVisited = [make a copy of alreadyVisited];
alreadyVisited.add(x*10+y);
The add will modify a new list, not the list that other invocations are using. (Personally, I'd declare a new variable such as newAlreadyVisited, since I don't really like modifying parameters, for readability reasons.)
This may seem inefficient. It will definitely use more memory (although the memory should be garbage-collectible pretty quickly). But trying to share a data structure between recursive invocations is very, very difficult to do correctly. It can be done if you're very careful about cleaning up the changes and restoring the structure to what it was when the method began. That might be necessary if the structure is something like a large tree, making it unfeasible to copy for every invocation. But it can take a lot of skill to make things work.
EDIT: I tested it and it appears to work: 12 if xRows=yColumns=2, 8512 if both are 4 (is that correct?). Another approach: instead of copying the list, I tried
alreadyVisited.remove((Object)(x*10+y));
at the end of the method ((Object) is needed so that Java doesn't think you're removing at an index) and that gave me the same results. If you do that, you'll make sure that alreadyVisited is the same when pathify returns as it was when it started. But I want to emphasize that I don't recommend this "cleanup" approach unless you really know what you're doing.
Java.
Is it normal that i get stack overflow error after 10 000 recursive void function calls with a reference and two integers as arguments?
Got 6gb ram memory, tried running through IDE and command line. I'm pretty sure the code is correct and recursion should finish.
It's about a Fill tool for a tile map editor. It start's at a certain tile and goes up, down, right and left if the coincident tile is of the same type and doesn't come back.
Tried different approaches, here is the one with additional boolean table indicating whether [x][y] tile was visited and replacing marked tiles after recursion is done:
public void fillRec(Tile t, int column, int row) {
if (affected[column][row] || t.getName() != pattern)
return;
/*t.replaceMe(editor.currentTileButton.spawnTile(column, row,
editor.tileMap));*/
affected[column][row] = true;
if (column < editor.tileMap.tilesX - 1) {
fillRec(editor.tileMap.tiles[column + 1][row], column + 1, row);
}
if (column > 0) {
fillRec(editor.tileMap.tiles[column - 1][row], column - 1, row);
}
if (row < editor.tileMap.tilesY - 1) {
fillRec(editor.tileMap.tiles[column][row + 1], column, row + 1);
}
if (row > 0) {
fillRec(editor.tileMap.tiles[column][row - 1], column, row - 1);
}
}
This works fine with ~75x75 map, so did functions replacing tile and doing other heavy stuff in their bodies.
Yes, each method call uses up a Stack frame. If you want to use large scale recursion in Java, you'll need to use a Trampoline - which can swap stack space for heap space. A trampoline typically has two states
completed
more work to do
The completed state holds the final result, and the more work to do can be implemented with a Supplier (in Java 8) or similar construct, that makes the next recursive call. The Trampoline implementation should manages the calls to your method, and iterates rather than recurses.
Here is a simple looping example with a Trampoline.
Trampoline<Integer> loop(int times,int sum){
if(times==0)
return Trampoline.done(sum);
else
return Trampoline.more(()->loop(times-1,sum+times));
}
To make the call to loop
loop(100,10).result();
Note the method returns a lazy Trampoline Object immediately (i.e. it doesn't perform the summing), and the Trampoline runs through the simple summing algorithm when result is called - in an iterative, rather than recursive fashion.
There is a Trampoline implementation in a library I wrote called cyclops-trampoline that you can use. Or if you prefer here is how to roll your own (this implementation makes use of a nice technique by Mario Fusco of managing the trampoline iteration in a Java 8 Stream).
public interface Trampoline<T> {
default Trampoline<T> bounce(){
return this;
}
T result();
default boolean complete() {
return true;
}
public static <T> Trampoline<T> done(T result) {
return () -> result;
}
public static <T> Trampoline<T> more(Trampoline<Trampoline<T>> trampoline) {
return new Trampoline<T>() {
#Override
public boolean complete() {
return false;
}
#Override
public Trampoline<T> bounce() {
return trampoline.result();
}
public T result() {
return trampoline(this);
}
T trampoline(Trampoline<T> trampoline) {
return Stream.iterate(trampoline,Trampoline::bounce)
.filter(Trampoline::complete)
.findFirst()
.get()
.result();
}
};
}
}
It depends on how much data these functions place on the stack in relation to the configured (or default) stack size, so it's not only the stack size used by the arguments to the function call.
So yes, it does not sound unnormal. You should play with the stack size or implement it differently.
That sounds normal. If you don't specify otherwise, the default Java stack size is 1Mb or less, depending on your JVM and execution platform. A stack overflow at ~10,000 recursive calls sounds quite plausible for a stack with the default size.
You can change the JVM's default stack size with the -Xss option; e.g. -Xss10m sets the default size to 10MB.
You can also specify a thread stack size directly via the Thread constructor.
However, this does illustrate a point that is not obvious to new Java programmers. Unlike typical functional programming languages (and many others) the standard Java implementations do not do "tail call optimization". This means that a recursive call sequence always needs stack space that is proportional to the maximum recursion depth.
This is a potential problem for programmers who prefer to use recursion rather than iteration. Unfortunately, if your data is such that deep recursion is a possibility, you really need to convert to an iterative solution. (Or find some other way to move the "recursion state" off the stack.)
This is a simplified example. I have this enum declaration as follows:
public enum ELogLevel {
None,
Debug,
Info,
Error
}
I have this code in another class:
if ((CLog._logLevel == ELogLevel.Info) || (CLog._logLevel == ELogLevel.Debug) || (CLog._logLevel == ELogLevel.Error)) {
System.out.println(formatMessage(message));
}
My question is if there is a way to shorten the test. Ideally i would like somethign to the tune of (this is borrowed from Pascal/Delphi):
if (CLog._logLevel in [ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error])
Instead of the long list of comparisons. Is there such a thing in Java, or maybe a way to achieve it? I am using a trivial example, my intention is to find out if there is a pattern so I can do these types of tests with enum value lists of many more elements.
EDIT: It looks like EnumSet is the closest thing to what I want. The Naïve way of implementing it is via something like:
if (EnumSet.of(ELogLevel.Info, ELogLevel.Debug, ELogLevel.Error).contains(CLog._logLevel))
But under benchmarking, this performs two orders of magnitude slower than the long if/then statement, I guess because the EnumSet is being instantiated every time it runs. This is a problem only for code that runs very often, and even then it's a very minor problem, since over 100M iterations we are talking about 7ms vs 450ms on my box; a very minimal amount of time either way.
What I settled on for code that runs very often is to pre-instantiate the EnumSet in a static variable, and use that instance in the loop, which cuts down the runtime back down to a much more palatable 9ms over 100M iterations.
So it looks like we have a winner! Thanks guys for your quick replies.
what you want is an enum set
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumSet.html
put the elements you want to test for in the set, and then use the Set method contains().
import java.util.EnumSet;
public class EnumSetExample
{
enum Level { NONE, DEBUG, INFO, ERROR };
public static void main(String[] args)
{
EnumSet<Level> subset = EnumSet.of(Level.DEBUG, Level.INFO);
for(Level currentLevel : EnumSet.allOf(Level.class))
{
if (subset.contains(currentLevel))
{
System.out.println("we have " + currentLevel.toString());
}
else
{
System.out.println("we don't have " + currentLevel.toString());
}
}
}
}
There's no way to do it concisely in Java. The closest you can come is to dump the values in a set and call contains(). An EnumSet is probably most efficient in your case. You can shorted the set initialization a little using the double brace idiom, though this has the drawback of creating a new inner class each time you use it, and hence increases the memory usage slightly.
In general, logging levels are implemented as integers:
public static int LEVEL_NONE = 0;
public static int LEVEL_DEBUG = 1;
public static int LEVEL_INFO = 2;
public static int LEVEL_ERROR = 3;
and then you can test for severity using simple comparisons:
if (Clog._loglevel >= LEVEL_DEBUG) {
// log
}
You could use a list of required levels, ie:
List<ELogLevel> levels = Lists.newArrayList(ELogLevel.Info,
ELogLevel.Debug, ELogLevel.Error);
if (levels.contains(CLog._logLevel)) {
//
}