Just spend two hours debugging this, I think I know the cause of the problem but I don't understand how can it produce the kind of results it does.
I've got a Swing based application where I override JPanel.paint(Graphics g) like this
public void paint(Graphics g) {
<snipped code>
Insets is = getInsets();
Dimension sz = getSize();
g2.setClip(is.left + 1, is.top + 1, sz.width - is.right - is.left - 2, sz.height - is.top - is.bottom - 2);
int w = getWidth();
int h = getHeight();
double s = Math.min(sz.getWidth(), sz.getHeight());
AffineTransform mc = g2.getTransform();
AffineTransform m1 = new AffineTransform(mc);
m1.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m1.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m1.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));
AffineTransform m2 = new AffineTransform(mc);
m2.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m2.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m2.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));
try {
m_InverseViewTransform = m1.createInverse();
} catch (NoninvertibleTransformException e) {
AffineTransform m3 = new AffineTransform(mc);
m3.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
m3.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
m3.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));
System.out.println("m1 = " + m1);
System.out.println("m2 = " + m2);
System.out.println("m3 = " + m3);
AffineTransform m4 = new AffineTransform(mc);
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getTranslateInstance(-m_CenterX, -m_CenterY));
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getScaleInstance(m_ScaleX * s, -m_ScaleY * s));
System.out.println("m4 = " + m4);
m4.preConcatenate(AffineTransform.getTranslateInstance(w / 2, h / 2));
System.out.println("m4 = " + m4);
System.out.println(w);
System.out.println(h);
System.out.println(s);
System.out.println(m_CenterX);
System.out.println(m_CenterY);
System.out.println(m_ScaleX);
System.out.println(m_ScaleY);
e.printStackTrace();
Now the mystery, sometimes when I launch the application ,more often than not, say three times out of four, the NoninvertibleTransformException is thrown.
As you can see to debug I output the offending matrix and three other identically calculated matrixes and the variables that are used to form those matrixes.
And this is where it gets interesting, see the output below, all the matrixes don't have the same value!
m1 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m2 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m3 = AffineTransform[[0.0, 0.0, 400.0], [0.0, -0.0, 289.0]]
m4 = AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
m4 = AffineTransform[[1.0, 0.0, -49.5], [0.0, 1.0, -0.362762953421903]]
m4 = AffineTransform[[5.254545454545455, 0.0, -260.1], [0.0, -587.9922126928986, 213.3017916655554]]
m4 = AffineTransform[[5.254545454545455, 0.0, 139.89999999999998], [0.0, -587.9922126928986, 502.3017916655554]]
800
578
578.0
49.5
0.36276295342190257
0.009090909090909092
1.0172875652126274
java.awt.geom.NoninvertibleTransformException: Determinant is 0
at java.awt.geom.AffineTransform.createInverse(AffineTransform.java:2706)
More interesting stuff, if I suitably move the debug output/calculations around to dig deep into this the problem disappears.
This happens only with JRE from jdk1.8.0_25.jdk (on Mac OS X 10.8.5), not with Java 1.6 or 1.6.
Ok, I think the real culprit is that the JPanel was not created in the Event Dispatched thread, once I did that the exception is never throw there are no inconsistencies.
So pretty obviously a thread related timing dependent problem but I'm curious how can this happen with in Java JVM 'rules' all the variable involved are local to the method and the the matrix methods from AffineTransform are not supposed to have side effects so kind of hard to understand how thread issues can cause something like this…
For my piece of mind I would like to understand what is going on here.
As a side effect this question may help some poor soul struggling with similar issues.
Also I don't mind if someone manages to pin point so obvious flaw in the code/debug/deductions as I've been staring at those lines now for hours….