Why static block are executed later? - java

P.S :
This question has been edited a few times as my previous code doesn't demonstrate the problem. There are some answers which may not make perfect sense against the edited question
I have a public class named Son.java
package com.t;
public class Son extends Father {
static int i;
static {
System.out.println("son - static");
i = 19;
}
{
System.out.println("son - init-block");
}
public static void main(String[] args) {
//Son s = new Son();
int a[] = new int[2];
System.out.println(a[5]);
}
}
class Father {
static {
System.out.println("f - static");
}
{
System.out.println("f - init-block");
}
}
When I run the program for the 1st time:
Output is:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at com.t.Son.main(Son.java:19)
f - static
son - static
And later when I run this program (order of output is random)
Output is:
f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at com.t.Son.main(Son.java:19)
I have read that static blocks are executed as the classes are initalised.
But why does the exception has come first here and then static block is executed?
I am using Eclipse too to run my program.
Can somebody explain?

The exception doesn't happen first, you are just seeing the printout of the exception first.
Had the exception happened first, you would never have seen the rest of the output.
The reason for this is that you have output to both System.err (from your exception) and System.out in your program. The order in which these are printed to the screen is not defined, so therefore you can get them in different order.

Stack traces of uncaught exceptions are printed in System.err, which is an unbuffered stream. You print text to System.out which is a buffered stream and it is unpredictable whether it he buffer gets flushed before or after the stack trace is printed.
If you change all your print statements to System.err then the order of the output will become the order of printing, and it will always be the same order.

#Keppil's answer has nailed it.
I just want to point out something ... erm ... interesting.
The OP says this:
I am using Eclipse to run my program.
The knee jerk response would be to say "that isn't relevant" ... but in this case, I think it >>is<< relevant. I suspect that non-determinism in stdout/stderr timing is being is amplified by the fact that the output is going to a Eclipse "console" panel.
When an application is run from the command line, output to stderr and stdout probably gets merged into out stream somewhere in the OS kernel. And if not, the console program probably uses a select syscall to handle input from two sources ... and gives one stream priority over the other, 'cos that is the easy way to code it. As a result, you would expect the output to appear on the console in a mostly consistent order, even though order is non-deterministic.
But when the application writes to an Eclipse console, Eclipse probably uses a separate thread to read each stream. Assuming that both threads are blocked in read syscalls, and input arrives at roughly the same time on both streams, it will be up to the thread scheduler to decide which thread gets woken first. That is going to be far less predictable that the behaviour of a select ... or of stream merging in the kernel.
Either way, my observation is that reordered stdout / stderr output is more prevalent with an Eclipse console than when you are using a "native" console.

As the asker said main belongs to Son class and is extending Father. I modified the code a little, so I was able to compile.
class Father {
static{
System.out.println("f - static");
}
}
public class Son extends Father {
static {
System.out.println("son - static");
}
public static void main(String[] args) throws ArrayIndexOutOfBoundsException{
int a[] = new int[2];
System.out.println(a[3]);
}
}
And the output is:-
f - static
son - static
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at kanwal.Son.main(Son.java:20)
Its working exactly, the way it is supposed to.
EDIT:-
This answer was made, before OP edited the question.

Related

Regarding manual termination of the program in eclipse java?

public class Test {
public static void main(String[] args)
{
while(true) {
System.out.println("1 ");
}
}
}
What this code does is run for infinite till the program is terminated manually for example give the picture below.
What my requirement is when I manually terminate the execution
my output should be like below
1
1
1
Program terminated manually
thank you
The above 2 lines of output after I manually terminate the program.
Why I need this is I am storing the serializable objects in the file. My code flow is when I working on the program there will be a lot of modifications in the object at end of execution I serialize the updated object into the file. So when I terminate the program manually serialization of the updated object is not done. So I need Serialization should be done even at manual termination.
You can add a hook to the shutdown event:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
//Do something here
}));
Edit: This doesn't work with eclipse, according to greg-449

Infinite recursive function -> Stack Overflow error

I have an infinite recursive loop in java
public void infiniteLoop(Long x){
System.out.println(""+x);
infiniteLoop(x + 1);
}
public static void main(String[] args) {
StackOverFlow st = new StackOverFlow();
st.infiniteLoop(0L);
}
In this piece of code it display an StackOverFlow error as expected, but if I look in the console output the error is displayed in multiple lines:
4806
4807
4808
at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)
at java.io.PrintStream.write(PrintStream.java:526)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at stackoverflow.StackOverFlow.infiniteLoop(StackOverFlow.java:234809
)
at stackoverflow.StackOverFlow.infiniteLoop(StackOverFlow.java:24)
at stackoverflow.StackOverFlow.infiniteLoop(StackOverFlow.java:24)
4810
4811
4812
My question is, why does this happens? shouldn't it stops as soon as the first Stack Overflow error is displayed?
[S]houldn't it stops as soon as the first Stack Overflow error is displayed?
Actually the program stops at the first stackoverflow exception. But exceptions are written to the stderr channel (so System.err.println(..)) whereas you print output to the stdout channel.
The terminal listens to both channels and aims to print them in a good way, but since these are separate channels, there is no guarantee that the order in which the producers write to the channels is displayed correctly: the order of the individual channels is always correct, but if data is written to both channels (almost) concurrently, the streams might be mixed up a bit.
You can alter your program to print to the stderr as well:
public void infiniteLoop(Long x){
System.err.println(""+x); // error channel.
infiniteLoop(x + 1);
}
Now the order in which data is written to the channel should also be the order in which it is displayed on the terminal.

Unable to execute Java code in SciTE

I have written a sample code:
import java.util.Scanner;
public class abcd {
public static void main(String[] args) {
System.out.print("please enter a: ");
Scanner a = new Scanner(System.in);
String b = a.next();
System.out.println(b);
}
}
I am able to compile and execute this code via Ubuntu terminal. In SciTe, it compiles fine, but when I run it, I am faced with this error:
please enter a: Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at abcd.main(abcd.java:8)
Any Suggestions?
EDIT: When I execute a file in terminal, I do: 'java abcd' Scite does: 'java -cp .abcd'. How are the two commands different and why isn't java -cp working?
It appears that there is a bug/improper implementation in the handling of standard input in SciTE on Linux/Unix.
The description of the bug and a workaround are in this PDF document: A Problem with SciTE Go Command on Linux
Note: this is not official documentation, but it seems to match your problem.
According to that document, when running a Java program through the "Go" command on SciTE, input is supposed to come from the output pane. However, on Linux this does not work properly, and it's as if you are reading from an empty stream.
When you are reading from an empty stream, Scanner sees the end-of-file marker when it attempts to read a value using next(), nextInt() etc. And it throws a NoSuchElementException as there is no input element in the stream.
Your options to work around this problem:
Try the method mentioned in the aforesaid document, to use "Go" in a Linux terminal instead of the output pane.
Run the program in a terminal and avoud the "Go" command altogether.
Use a different IDE which doesn't have this problem.
Try to use hasNext() before next();
import java.util.Scanner;
public class abcd {
public static void main(String[] args) {
System.out.print("please enter a: ");
Scanner a = new Scanner(System.in);
while(a.hasNext()) {
try {
String b = a.next();
System.out.println(b);
} catch (NoSuchElementException e) {}
}
}
}
I don't mean to offend, but using hasNext() as suggested in Alexander's answer won't solve this problem, it will only enable OP to handle it well. I don't think that is what he/she is looking for.
Now I am no expert by any means and for some reason your program code works on my machine... But anyways, a NoSuchElementException is thrown when your program is cycling over an iterable object and there is nothing more to cycle over, despite your program expecting something there. A quick look-up in the Java-docs of Scanner.next()
shows that this exception is thrown if there are no more tokens available for read.
Now, if I had to guess I would advise you to try using something other than Scanner.next() and see if that works.
The fact that it works on my machine but not on yours is somewhat surprising, so could you provide some information on how you try to run your program? Are you running it from the default command-line? Or within Scite? (If second is the case, I really won't be able to help you, I have never even touched Scite).

How to findout main method has called by JVM or existing process?

Considering the following code
public static void main(String...arg){
//do something
if(<<the method has called by a new process>>){System.exit(0);}
else{System.setProperty("main_result","0");return;}
}
the main method would be called by a separated process by JVM or existing process, now how can I find it out?
Thanks in advance
Let's clarify: there might be another class with a main that was started, or the main is somehow called again.
Normally you want to call System.exit(0) (or return;?) but when called from the program itself you want to end in System.setProperty("main_result","0");.
public static void otherMain(String[] args) {
Main.main(args);
}
public static void main(String[] args) {
...
StackTraceElement[] elems = Thread.currentThread().getStackTrace();
//for (StackTraceElement elem : elems) {
// System.out.printf("%s%n", elem.getClassName());
//}
if (elems.length > 2) { // [0] Thread [1] main
System.setProperty("main_result","0");
}
}
In java, every Java process runs in its own JVM. So, the "same" main
method cannot be called by a different process under normal
circumstances
Even if you run the same program twice, they will be running in their
own JVMs.
You can try one thing.. Keep a static variable in your program, run it and
make it sleep for a long period of time (process 1).. Now, run the same
program again and update the static variable(runs in process 2).. See, whether it will be
updated in the first process (No, it won't be updated as each process will have it's own
set of variables..)
Do you really need it? Just don't use System.exit(0); and refactor main method to finish gracefully.
Calling System.setProperty in both cases - when run as new process and also as a class on classpath, will not make any difference.
Edit: Finding out who is calling the method is not easy and definitely bad practice.
I would refactor the code as follows:
public static void main(String...arg){
System.exit(doStuff(arg));
}
public static int doStuff(String... arg) {
//do something
}
To access this logic within the same JVM you can now call MyClass.doStuff and get the return value directly.
It would be better to consider refactoring and get rid of such problem.
Otherwise the following code can help:
if(Thread.currentThread().getStackTrace()[1].getClassName().equals(
System.getProperty("sun.java.command"))){
System.out.println("!");
}
Will not work if there is no "sun.java.command" property (on not Sun/Oracle JVMs it may absent)

Java entering an if statement that is false

I'm running into the strangest error in this program, which is confirmed when debugging it. I have the following code (boiled down to highlight the problem, of course):
BHFrame.java
public class BHFrame
{
private boolean uSS;
private StateSaver stateSaver;
public BHFrame(boolean useInternalStateSaver)
{
//Init code
uSS = useInternalStateSaver;
//More init code
System.out.println(uSS);
if (uSS)
{System.out.println("Entered 1");
stateSaver = new StateSaver(title, false);
stateSaver.addSaveable(getThis());
}
//More init code
System.out.println(uSS);
if (uSS)
{System.out.println("Entered 2");
try
{
stateSaver.loadState();
stateSaver.putState(getThis());
}
catch (IOException ex)
{
alertUserOfException(ex);
}
}
}
}
GUI.java
public class GUI extends BHFrame
{
public GUI(boolean useInternalStateSaver)
{
super(useInternalStateSaver);
}
}
Main.java
public class Main
{
public static void main(String[] args)
{
GUI gui = new GUI(false);
}
}
Output
false
false
Entered 2
Exception in thread "main" java.lang.NullPointerException
at bht.tools.comps.BHFrame.<init>(BHFrame.java:26)
at bhms.GUI.<init>(GUI.java:5)
at bhms.Main.main(Main.java:5)
The class BHFrame is extended and run from a child class that calls this constructor, but that really shouldn't affect this behavior. The problem is that, when false is passed to the constructor as useInternalStateSaver, the first if (uSS) is skipped, but the second is entered. Upon debugging, I found that uSS is false throughout runtime, including on the line of the second if statement, here. Why would Java enter an if statement when the condition returns false? Before you ask, I did delete the .class files and recompile it just in case there was some residual code messing with it, but I got the same result. And rest assured, all the references to the uSS variable are displayed here.
Solution
As it turns out, this appears to be a bug in NetBeans 7.1 Build 201109252201, wherein the IDE doesn't properly insert new code into the compiled .class files. The problem was fixed by compiling the files externally. A bug report has been submitted.
Whatever's throwing that exception is probably not in your posted code.
It's not being caught by your catch statement, which only catches IOException.
It's a NullPointerException and can occur anywhere.
You have shown no indication that the code inside your if block is actually executing. In your screenshot, there is absolutely know way of knowing if your if block is entered or not. There are no logging statements.
Add debugging messages at various points to see exactly what is happening. Or, you know, look at line 26 (wayyyyy before your posted code) to see why you're getting a NullPointerException.
I've seen crazy stuff like this when there is bad RAM on the machine. You might want to run memtest86.
You might also consider deleting all of your project class files, and then doing a build. Maybe you changed Main.java, but it was never recompiled. I hate that when that happens.
This is just a guess, because I can't see the code you are mentioning, but I reckon you have defined a local variable uSS in the second //More init code segment.
Once you define a local variable named the same as an instance variable, it 'hides' the instance variable. Better to qualify all instance variables with this.
So, try qualifying all above accesses of uSS with this. ... (this.uSS)
Even if this isn't the issue, it might be better to post the full code anyway.
HTH

Categories