1

I have the following piece of code.

At any point of time, can the value print for i be still 0. For the above execution I am not able to reproduce it. But in a production code I am getting the value 0.

I am having a production code with static initialization block. Somehow the one of the methods gets executed before the static block finishes its execution.

class TestStatic {

    private int i = 0;

    public static TestStatic testStatic = null;

    static {
        testStatic = new TestStatic();
        try {
            BufferedReader reader = new BufferedReader(new FileReader("C:\\Users\\I338224\\Documents\\temp\\src\\Test.xml"));
            final StringBuilder builder = new StringBuilder();
            final DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setIgnoringElementContentWhitespace(true);
            docBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            DocumentBuilder docBuilder = null;
            docBuilder = docBuilderFactory.newDocumentBuilder();
            for(long i=0;i<1000000000;i++);
            Document d = docBuilder.parse("C:\\Users\\I338224\\Documents\\temp\\src\\Test.xml");
            reader.lines().forEach(line -> builder.append(line).append("\n"));
            System.out.println(builder.length());
            testStatic.i = 5;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        }
    }

    public static TestStatic getInstance(){
        return testStatic;
    }

    public void display(){
        System.out.println(i);
    }
}

public class Test {

    public static void main(String[] args) {

        Runnable r = () -> {
            TestStatic.getInstance().display();
        };
        Runnable r2 = () -> {
            TestStatic.getInstance().display();
        };
        Thread t1 = new Thread(r);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
    }
}

The expected result is that the value printed for i should be 5. But it is 0.

c0der
  • 18,467
  • 6
  • 33
  • 65
  • 2
    The only way for `TestStatic.i` to be equal to 0 is if exception is thrown in `static` block. But then you will be able to see a stacktrace in log files. – Ivan Jul 26 '19 at 13:42
  • @Ivan I completely missed that - good shout, I've removed my answer as it's misleading considering it doesn't mention exceptions. +1 from me if you put it as an answer (bear in mind that if the exception isn't one that's caught here, depending on the default exception handler, it may not make its way to the log files.) – Michael Berry Jul 26 '19 at 13:59

1 Answers1

1

The following is mcve of your code.
It prints out 0 only if you un comment if(true) throw new IllegalStateException("Exception");:

import java.util.concurrent.TimeUnit;

class TestStatic {

    private int i = 0;
    public static TestStatic testStatic = null;

    static {
        testStatic = new TestStatic();
        try {
            TimeUnit.SECONDS.sleep(1);
            //if(true) throw new IllegalStateException();
            testStatic.i = 5;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static TestStatic getInstance(){
        return testStatic;
    }

    public void display(){
        System.out.println(i);
    }
}

public class Test {

    public static void main(String[] args) {
        new Thread(() -> TestStatic.getInstance().display()).start();
        new Thread(() -> TestStatic.getInstance().display()).start();
    }
}
c0der
  • 18,467
  • 6
  • 33
  • 65