While practising Java arrays in Eclipse, I have encountered this weird behaviour of arrays.
public class base3 {
public static void main(String[] args) {
int arr[]= new int[25];
System.out.println(arr[0]);
//System.out.println(arr[25]);
System.out.println(arr[-10]);
}
}
Output of this is:
0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -10
at base3.main(base3.java:6)
But as soon as I change the index of third sysout from -10 to -11, the sequence of output changes.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -11
at base3.main(base3.java:6)
0
So why does the output sequence changes along with array index.
This is happening due to the the output is written to different file. The output 0 is printed to standard output(fd 1) and the exception to standard error(fd 2). You could see this when you redirect standard error to /dev/null
❯ java base3 2>/dev/null
0
See how you don't get exception here. So the order here will not be predictable due to output written to different files.
The java documentation says Prints this throwable and its backtrace to the standard error stream..
I think you are looking at a race condition between standard error and standard out to print things to the console. When the exception ArrayIndexOutOfBoundsException gets thrown, it is not handled by printing to System.out but to System.err. Since both streams have to share the console resource the order in which they get access determines the order of the print statements.
The change of -10 to -11 should not influence the result. It is the time between the call to System.out.println(arr[0]); and System.out.println(arr[-10]); that influences the order of the output.
Related
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 1 year ago.
Here i am getting this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
String input = keyboard.nextLine();
System.out.println(input);
while(true){
if(args[0].equals("k")){
System.out.println("k");
}
}
}
You need run the code on cmd as java MyProgram abc xyz then args will contain ["abc", "xyz"].Maybe you are not doing that right now and therefore getting the error.
You need to provide Command Line Arguments like so:
java MyClass k foo bar
These arguments are passed to the array args[] which will then contain {"k", "foo", "bar"}
Therefore args.length will be 3 and args[0] will be k
If you are executing through IDE and not setting arguments OR not passing command line arguments while running through cmd, you'll get this error.
But for this program, even if you pass arguments, it will run in infinite loop probably as while condition is always true.
You are executing this java class without arguments. In that case, args[0] does now exist, and thus the Exception with Error message.
You can modify the if in this form:
if(args[0].equals("k") && args.length > 0 )
so you do not get exception with message
Index 0 out of bounds for length 0
Your program is producing output without error, when Running the program with argument "k" produces the infinite look of printing k. For this you need to run command the java printKjavaFile k , or start it from IDE with this argument.
You are doing 2 things at the same time:
ask for user input via stdin, when the program is running already
parsing the args[], which should be given when the program starts to run
and expect they work together. But they are different.
I suppose you run the app like: java MyClass without adding extra args after this. You can:
provide arg k after java MyClass, so args[] becomes a non-empty array
stop trying to use args, but just focus on input, which is the line you read from user input.
I am trying to code this program to read 6 values from the command line as coordinates and use these coordinates to calculate the area and perimeter of the triangle formed.
However, I'm getting this error message when running the program:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at geometry.ThreePoints.main(ThreePoints.java:26)
What's going wrong?
My Code with the error message:
you are running your program without any argument in eclipse.
go to run > run configuration and add arguments:
This programm doens't read from command line, it reads the start arguments. which i guess are not there.
edit:
an example for reading from the command line, you'll find at the oracle docs
Looks like you are not passing parameters while trying to run the program.
Go to run configuration in eclipse and add your parameters there. this will fix your problem.
In eclipse Go To RunAs-->Run Configurations.. --> Arguments --> Program Arguments.
Put there arguments whitespace separated.
Use args.length to check the length of arguments.
Use args.length to determine the number of arguments before you read them.
if (args.length < 6) {
System.out.println("Number of argument too small. Must be 6, but was "+ args.length +".");
}
You've probably made a mistake entering the arguments. You should always check the number of array elements before you access them!
I was wondering what happens when you try to catch an StackOverflowError and came up with the following method:
class RandomNumberGenerator {
static int cnt = 0;
public static void main(String[] args) {
try {
main(args);
} catch (StackOverflowError ignore) {
System.out.println(cnt++);
}
}
}
Now my question:
Why does this method print '4'?
I thought maybe it was because System.out.println() needs 3 segments on the call stack, but I don't know where the number 3 comes from. When you look at the source code (and bytecode) of System.out.println(), it normally would lead to far more method invocations than 3 (so 3 segments on the call stack would not be sufficient). If it's because of optimizations the Hotspot VM applies (method inlining), I wonder if the result would be different on another VM.
Edit:
As the output seems to be highly JVM specific, I get the result 4 using
Java(TM) SE Runtime Environment (build 1.6.0_41-b02)
Java HotSpot(TM) 64-Bit Server VM (build 20.14-b01, mixed mode)
Explanation why I think this question is different from Understanding the Java stack:
My question is not about why there is a cnt > 0 (obviously because System.out.println() requires stack size and throws another StackOverflowError before something gets printed), but why it has the particular value of 4, respectively 0,3,8,55 or something else on other systems.
I think the others have done a good job at explaining why cnt > 0, but there's not enough details regarding why cnt = 4, and why cnt varies so widely among different settings. I will attempt to fill that void here.
Let
X be the total stack size
M be the stack space used when we enter main the first time
R be the stack space increase each time we enter into main
P be the stack space necessary to run System.out.println
When we first get into main, the space left over is X-M. Each recursive call takes up R more memory. So for 1 recursive call (1 more than original), the memory use is M + R. Suppose that StackOverflowError is thrown after C successful recursive calls, that is, M + C * R <= X and M + C * (R + 1) > X. At the time of the first StackOverflowError, there's X - M - C * R memory left.
To be able to run System.out.prinln, we need P amount of space left on the stack. If it so happens that X - M - C * R >= P, then 0 will be printed. If P requires more space, then we remove frames from the stack, gaining R memory at the cost of cnt++.
When println is finally able to run, X - M - (C - cnt) * R >= P. So if P is large for a particular system, then cnt will be large.
Let's look at this with some examples.
Example 1: Suppose
X = 100
M = 1
R = 2
P = 1
Then C = floor((X-M)/R) = 49, and cnt = ceiling((P - (X - M - C*R))/R) = 0.
Example 2: Suppose that
X = 100
M = 1
R = 5
P = 12
Then C = 19, and cnt = 2.
Example 3: Suppose that
X = 101
M = 1
R = 5
P = 12
Then C = 20, and cnt = 3.
Example 4: Suppose that
X = 101
M = 2
R = 5
P = 12
Then C = 19, and cnt = 2.
Thus, we see that both the system (M, R, and P) and the stack size (X) affects cnt.
As a side note, it does not matter how much space catch requires to start. As long as there is not enough space for catch, then cnt will not increase, so there are no external effects.
EDIT
I take back what I said about catch. It does play a role. Suppose it requires T amount of space to start. cnt starts to increment when the leftover space is greater than T, and println runs when the leftover space is greater than T + P. This adds an extra step to the calculations and further muddies up the already muddy analysis.
EDIT
I finally found time to run some experiments to back up my theory. Unfortunately, the theory doesn't seem to match up with the experiments. What actually happens is very different.
Experiment setup:
Ubuntu 12.04 server with default java and default-jdk. Xss starting at 70,000 at 1 byte increments to 460,000.
The results are available at: https://www.google.com/fusiontables/DataSource?docid=1xkJhd4s8biLghe6gZbcfUs3vT5MpS_OnscjWDbM
I've created another version where every repeated data point is removed. In other words, only points that are different from the previous are shown. This makes it easier to see anomalies. https://www.google.com/fusiontables/DataSource?docid=1XG_SRzrrNasepwZoNHqEAKuZlHiAm9vbEdwfsUA
This is the victim of bad recursive call. As you are wondering why the value of cnt varies, it is because the stack size depends on the platform. Java SE 6 on Windows has a default stack size of 320k in the 32-bit VM and 1024k in the 64-bit VM. You can read more here.
You can run using different stack sizes and you will see different values of cnt before the stack overflows-
java -Xss1024k RandomNumberGenerator
You don't see the value of cnt being printed multiple times even though the value is greater than 1 sometimes because your print statement is also throwing error which you can debug to be sure through Eclipse or other IDEs.
You can change the code to the following to debug per statement execution if you'd prefer-
static int cnt = 0;
public static void main(String[] args) {
try {
main(args);
} catch (Throwable ignore) {
cnt++;
try {
System.out.println(cnt);
} catch (Throwable t) {
}
}
}
UPDATE:
As this getting a lot more attention, let's have another example to make things clearer-
static int cnt = 0;
public static void overflow(){
try {
overflow();
} catch (Throwable t) {
cnt++;
}
}
public static void main(String[] args) {
overflow();
System.out.println(cnt);
}
We created another method named overflow to do a bad recursion and removed the println statement from the catch block so it doesn't start throwing another set of errors while trying to print. This works as expected. You can try putting System.out.println(cnt); statement after cnt++ above and compile. Then run multiple times. Depending on your platform, you may get different values of cnt.
This is why generally we do not catch errors because mystery in code is not fantasy.
The behavior is dependent upon the stack size (which can be manually set using Xss. The stack size is architecture specific. From JDK 7 source code:
// Default stack size on Windows is determined by the executable (java.exe
// has a default value of 320K/1MB [32bit/64bit]). Depending on Windows version, changing
// ThreadStackSize to non-zero may have significant impact on memory usage.
// See comments in os_windows.cpp.
So when the StackOverflowError is thrown, the error is caught in catch block. Here println() is another stack call which throws exception again. This gets repeated.
How many times it repeates? - Well it depends on when JVM thinks it is no longer stackoverflow. And that depends on the stack size of each function call (difficult to find) and the Xss. As mentioned above default total size and size of each function call (depends on memory page size etc) is platform specific. Hence different behavior.
Calling the java call with -Xss 4M gives me 41. Hence the correlataion.
I think the number displayed is the number of time the System.out.println call throws the Stackoverflow exception.
It probably depend on the implementation of the println and the number of stacking call it is made in it.
As an illustration:
The main() call trigger the Stackoverflow exception at call i.
The i-1 call of main catch the exception and call println which trigger a second Stackoverflow. cnt get increment to 1.
The i-2 call of main catch now the exception and call println. In println a method is called triggering a 3rd exception. cnt get increment to 2.
this continue until println can make all its needed call and finally display the value of cnt.
This is then dependent of the actual implementation of println.
For the JDK7 either it detect cycling call and throws the exception earlier either it keep some stack resource and throw the exception before reaching the limit to give some room for remediation logic either the println implementation doesn't make calls either the ++ operation is done after the println call thus is by pass by the exception.
main recurses on itself until it overflows the stack at recursion depth R.
The catch block at recursion depth R-1 is run.
The catch block at recursion depth R-1 evaluates cnt++.
The catch block at depth R-1 calls println, placing cnt's old value on the stack. println will internally call other methods and uses local variables and things. All these processes require stack space.
Because the stack was already grazing the limit, and calling/executing println requires stack space, a new stack overflow is triggered at depth R-1 instead of depth R.
Steps 2-5 happen again, but at recursion depth R-2.
Steps 2-5 happen again, but at recursion depth R-3.
Steps 2-5 happen again, but at recursion depth R-4.
Steps 2-4 happen again, but at recursion depth R-5.
It so happens that there is enough stack space now for println to complete (note that this is an implementation detail, it may vary).
cnt was post-incremented at depths R-1, R-2, R-3, R-4, and finally at R-5. The fifth post-increment returned four, which is what was printed.
With main completed successfully at depth R-5, the whole stack unwinds without more catch blocks being run and the program completes.
After digging around for a while, I can't say that I find the answer, but I think it's quite close now.
First, we need to know when a StackOverflowError will be thrown. In fact, the stack for a java thread stores frames, which containing all the data needed for invoking a method and resume. According to Java Language Specifications for JAVA 6, when invoking a method,
If there is not sufficient memory available to create such an activation frame, an StackOverflowError is thrown.
Second, we should make it clear what is "there is not sufficient memory available to create such an activation frame". According to Java Virtual Machine Specifications for JAVA 6,
frames may be heap allocated.
So, when a frame is created, there should be enough heap space to create a stack frame and enough stack space to store the new reference which point to the new stack frame if the frame is heap allocated.
Now let's go back to the question. From the above, we can know that when a method is execute, it may just costs the same amount of stack space. And invoking System.out.println (may) needs 5 level of method invocation, so 5 frames need to be created. Then when StackOverflowError is thrown out, it has to go back 5 times to get enough stack space to store 5 frames' references. Hence 4 is print out. Why not 5? Because you use cnt++. Change it to ++cnt, and then you will get 5.
And you will notice that when the size of stack go to a high level, you will get 50 sometimes. That is because the amount of available heap space need to be taken into consideration then. When the stack's size is too large, maybe heap space will run out before stack. And (maybe) the actual size of stack frames of System.out.println is about 51 times of main, therefore it goes back 51 times and print 50.
This is not exactly an answer to the question but I just wanted to add something to the original question that I came across and how I understood the problem:
In the original problem the exception is caught where it was possible:
For example with jdk 1.7 it is caught at first place of occurence.
but in earlier versions of jdk it looks like the exception is not being caught at the first place of occurence hence 4, 50 etc..
Now if you remove the try catch block as following
public static void main( String[] args ){
System.out.println(cnt++);
main(args);
}
Then you will see all the values of cnt ant the thrown exceptions (on jdk 1.7).
I used netbeans to see the output, as the cmd will not show all the output and exception thrown.
My code is as follows:
public class BoxingUnboxingExample {
public static void main(String[] args) {
Integer i1 = null;
Integer i3 = 10;
BoxingUnboxingExample b = new BoxingUnboxingExample();
b.go(i3);
b.go(i1);
}
private void go(int a){
System.out.println("a");
}
}
Now my question is:
Sometimes I get the following error message,
Exception in thread "main" java.lang.NullPointerException
at scjp.wraperExample.BoxingUnboxingExample.main(BoxingUnboxingExample.java:12)
a
Whereas, I think It should always be the following,
a
Exception in thread "main" java.lang.NullPointerException
at scjp.wraperExample.BoxingUnboxingExample.main(BoxingUnboxingExample.java:12)
Am I correct?
One reason could be the exception stack trace uses standard error (System.err) to output the error data while System.out.println uses standard output (System.out).
That means both are using different mechanisms to output the data, these may not be properly synchronized.
You can also refer this earlier question.
ex
If you are in Eclipse, this is a known problem, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=32205
Output and Error are two different streams System.err and System.out.
Read this:
It is acceptable—and normal—for standard output and standard error to
be directed to the same destination, such as the text terminal.
Messages appear in the same order as the program writes them, unless
buffering is involved. (For example, a common situation is when the
standard error stream is unbuffered but the standard output stream is
line-buffered; in this case, text written to standard error later may
appear on the terminal earlier, if the standard output stream's buffer
is not yet full.)
from wikipeda
so your output stream (System.out.println) is actually buffered. Internally it calles the BufferedWriter.write() methode. take alook at this:
How System.out.println() really works
There are at least 2 effects at play here, both related to how System.out and System.err are (naturally) 2 different streams.
Buffering
System.err and System.out are both PrintStreams, which are buffered by default, however System.err is usually set to auto-flush after every write (of a byte array or whenever a newline is written).
As such, if System.err is flushed before System.out is flushed, it will appear on screen first.
The reading of those streams
In editors, it is not uncommon for both System.out and System.err to be displayed within a single console. The way this happens will influence the order in which they are displayed. Eclipse has 2 processes, one for every stream, to read from the streams and display them. The order in which they will read (and as such, display) is non-deterministic. The process that reads from System.err would have a 50% chance of being the first to receive input if both streams are written to quasi-simultanously. As such, they may appear to be randomly interleaved.
public class Main {
public static void main(String[] args) {
System.setErr(System.out); // this line seems to solve the problem
System.out.println("test");
throw new RuntimeException("Test");
}
}
I'm trying to run my code and it says something about the exception:
java.lang.ArrayIndexOutOfBoundsException
I googled it, from what I understand it happens when I try to access an index that's negative or greater than my array length.
But I can't seem to find the problem, here's my code: http://pastebin.com/sXsBbYfh
Thanks for any helpers.
EDIT: the error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at Calculator.addOne(Calculator.java:127)
at Calculator.add(Calculator.java:88)
at Program.main(Program.java:8)
About the relevant part of the code, I have no idea, that's why i'm coming to you.
The issue would appear to be with line 86
arrResult = this.addOne(arrResult.length);
Array indexes are 0 based, so 0 - length-1 and you are passing length in and then using that to access your array on line 127
switch(arrResult[arrayIndex])
This part of code :
public int[] addOne(int arrayIndex)
124.
{
125.
switch(arrResult[arrayIndex])
126.
{
127.
case 0:
128.
arrResult[arrayIndex] = 1;
Is source of error.
Note that.
In java, arrays index range from 0 to length-1
In your code above, when method addon() is called , you are passing array length as parameter, and in code above you are trying to access array[length] which does not exist and hence the exception. Thus you may want to keep that length-1
In the following code line #86
arrResult = this.addOne(arrResult.length);
There are lot of logical errors in your code. This is just the one that throws the exception you mentioned