JDK-4836495 : JVM crashes trying to draw very small Arc2D pie fraction when antialiasing is on
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.3.1_07,1.4.0,1.4.1_02,1.4.2,5.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    generic,solaris_7,solaris_8,solaris_9,windows_2000 generic,solaris_7,solaris_8,solaris_9,windows_2000
  • CPU: generic,sparc
  • Submitted: 2003-03-24
  • Updated: 2003-06-27
  • Resolved: 2003-04-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other Other
1.3.1_09 09Fixed 1.4.1_05Fixed 1.4.2Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
JVM crashes trying to draw very small Arc2D pie fraction when antialiasing 
is on. The problem is easily reproducible.

1. Testcase
-----------
% more CrashVM.java
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Date;

public class CrashVM {

    public static void main(String[] args) {
       
        BufferedImage image = new BufferedImage(400, 300, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = (Graphics2D) image.getGraphics();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        Rectangle2D bounds = new Rectangle2D.Double(168.83125, 54.60624999999999, 162.33749999999998, 162.33749999999998
);
        Arc2D arc = new Arc2D.Double(bounds, 90.0, -4.2154566415320005E-7, Arc2D.PIE);
        System.out.println("About to draw...");
        g2.draw(arc);
        System.out.println("Done --> " + new Date().toString());
    }
}
%


2. Compile
----------

% /j2sdk1_3_1_07/bin/java -version
java version "1.3.1_07"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_07-b02)
Java HotSpot(TM) Client VM (build 1.3.1_07-b02, mixed mode)
% /j2sdk1_3_1_07/bin/javac CrashVM.java
% 


3. Run
------

% /j2sdk1_3_1_07/bin/java CrashVM
About to draw...
Segmentation Fault (core dumped)
%


4. Core file
------------

% dbx -V /net/cores/tsc/Applix/java/JDK/j2sdk1_3_1_07/bin/sparc/native_threads/java ./core
Sun WorkShop 6 update 2 Dbx Debugger 6.2 2001/05/16
Reading java
core file header read successfully
Reading ld.so.1
Reading libthread.so.1
Reading libdl.so.1
Reading libc.so.1
Reading libc_psr.so.1
Reading libjvm.so
Reading libCrun.so.1
Reading libsocket.so.1
Reading libnsl.so.1
Reading libm.so.1
Reading libw.so.1
Reading libmp.so.2
Reading libhpi.so
Reading libverify.so
Reading libjava.so
Reading libzip.so
Reading libawt.so
Reading libmawt.so
Reading libmlib_image.so
Reading libXm.so.4
Reading libXt.so.4
Reading libXext.so.0
Reading libXtst.so.1
Reading libX11.so.4
Reading libSM.so.6
Reading libICE.so.6
Reading libfontmanager.so
Reading libdps.so.5
Reading libdcpr.so
detected a multithreaded program
t@1 (l@4) terminated by signal SEGV (Segmentation Fault)
0xfaecb888: processToRunsArc3+0x0070:   st      %f0, [%sp + 0x80]
dbx: core file read error: address 0xffb75f40 not in data space
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) where
current thread: t@1
=>[1] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecb888
  [2] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [3] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [4] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [5] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [6] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [7] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [8] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [9] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
[ ... ]
  [100] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) where -f 2000
current thread: t@1
  [2000] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
[ ... ]
  [2045] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [2046] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [2047] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [2048] processToRunsArc3(0xfaef93a0, 0x10de84, 0xfaee66f8, 0x3d800000, 0x7fffffff, 0x7fffffff), at 0xfaecbcc4
  [2049] RunsBuilder_appendCubic(0x27a58, 0x27a84, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff), at 0xfaeca97c
  [2050] appendCubic_describeTo(0x27a58, 0x1c3cf0, 0x27a84, 0x34, 0x1c3d48, 0x0), at 0xfaec449c
  [2051] sendTo(0x1c3cf0, 0x27a84, 0x27a84, 0x27a58, 0x2, 0x2), at 0xfaec489c
  [2052] setOutputArea(0x10dbfc, 0x10de84, 0x3, 0x27a58, 0x1, 0x53), at 0xfaecd7c8
  [2053] Java_sun_dc_pr_PathFiller_setOutputArea(0x27a58, 0xffbee21c, 0x437a0000, 0x42540000, 0x2, 0x53), at 0xfaec5c0c
  [2054] 0x7e1c8(0xf4c13a20, 0xffbee620, 0x29810, 0xfe73c000, 0xb6, 0xf8d848e8), at 0x7e1c7
  [2055] 0x7b58c(0xf4c13a00, 0xffbee620, 0x29810, 0x83c7c, 0xb6, 0xf8d80bf0), at 0x7b58b
  [2056] 0x7b58c(0xf4c135b8, 0xffbee620, 0x29810, 0x83c7c, 0xb6, 0xf8d80b10), at 0x7b58b
  [2057] 0x7b58c(0xf4c135b8, 0x7d5d8, 0x29810, 0x83c7c, 0xf8d3a0c0, 0x6), at 0x7b58b
  [2058] 0x7b834(0xf4c07530, 0x7d5d8, 0x29810, 0x83f04, 0xf8d320f8, 0x0), at 0x7b833
  [2059] 0x7b834(0xf4c07558, 0xffbee620, 0x29810, 0x83f04, 0xb6, 0xf8ca0690), at 0x7b833
  [2060] 0x7b58c(0x0, 0x1, 0xfe749698, 0x83c7c, 0x1e, 0xe), at 0x7b58b
  [2061] 0xfe772bb4(0xffbee640, 0xffbee840, 0xa, 0xf8c9cf10, 0x7d5d8, 0xffbee774), at 0xfe772bb3
  [2062] JavaCalls::call_helper(0xffbee838, 0xfe73c000, 0xffbee76c, 0x29810, 0x7d5d8, 0xffbee840), at 0xfe5032c0
  [2063] JavaCalls::call(0xffbee838, 0xffbee74c, 0xffbee76c, 0x29810, 0xfe73c000, 0xffbee6e4), at 0xfe502f50
  [2064] jni_invoke(0x1, 0x29810, 0x0, 0x0, 0xa53b0, 0xffbee81c), at 0xfe516a60
  [2065] jni_CallStaticVoidMethod(0xfe73c000, 0x29810, 0xa53b0, 0x2989c, 0xffbee8a0, 0x29810), at 0xfe56b1cc
  [2066] main(0x2989c, 0x0, 0x2989c, 0xffbef30c, 0x0, 0x2503c), at 0x11ca4
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx)




Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_09 1.4.1_05 mantis-rc tiger FIXED IN: 1.3.1_09 1.4.1_05 mantis-rc tiger INTEGRATED IN: 1.3.1_09 1.4.1_05 mantis-b20 mantis-rc tiger tiger-b08 VERIFIED IN: mantis-rc
14-06-2004

EVALUATION Name: spR10137 Date: 03/26/2003 The point of SIGSEGV is anglesOct1*() macro definitions in native part of Ductus code. We use floats casted to ints to get values from corresponding tables (angleOct1*Table). In case we have NaN as parameter, we have index which points far from array bounds. Now about the origin of NaN for this testcase. It comes from AcrIterator, method btan(double): private static double btan(double increment) { increment /= 2.0; double a = 1.0 - Math.cos(increment); double b = Math.tan(increment); double c = Math.sqrt(1.0 + b * b) - 1.0 + a; return 4.0 / 3.0 * a * b / c; } For extremely small angles a = 0, b equals to angle, that is, b is extremely small too. So, b * b becomes zero, then c = 0. We return NaN as result. All operations with NaN give us NaNs too. Really btan's formula has more simple equivalents: 4.0 / 3.0 * (1.0 - Math.cos(increment)) / Math.sin(increment) (I) 4.0 / 3.0 * Math.sin(increment) / (1.0 + Math.cos(increment)) (II) Ductus uses first variant (see dcPathStroker.c, cubicCircleApproximation method). I guess, second variant is a bit more safe (probably we can find the value of increment to make Math.sin(increment) == 0). -- Sergi (###@###.###) ======================================================================
11-06-2004

WORK AROUND 1) Don't use AntiAliasing: Comment the following lines: 14 // g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 15 // RenderingHints.VALUE_ANTIALIAS_ON); % /j2sdk1_3_1_07/bin/java -version java version "1.3.1_07" Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_07-b02) Java HotSpot(TM) Client VM (build 1.3.1_07-b02, mixed mode) % /j2sdk1_3_1_07/bin/javac CrashVM.java % /j2sdk1_3_1_07/bin/java CrashVM About to draw... Done --> Mon Mar 24 12:43:47 CET 2003 % 2) Round values to small Workaround would be to find the exact interval and round to 0.001 (upper bound) or to 0 (lower bound), in order to avoid the problem in JFreeChart.
11-06-2004

SUGGESTED FIX Name: spR10137 Date: 03/26/2003 ------- ArcIterator.java ------- *** /tmp/sccs.1maqLf Wed Mar 26 19:25:19 2003 --- ArcIterator.java Wed Mar 26 19:04:43 2003 *************** *** 82,91 **** private static double btan(double increment) { increment /= 2.0; ! double a = 1.0 - Math.cos(increment); ! double b = Math.tan(increment); ! double c = Math.sqrt(1.0 + b * b) - 1.0 + a; ! return 4.0 / 3.0 * a * b / c; } /** --- 82,88 ---- private static double btan(double increment) { increment /= 2.0; ! return 4.0 / 3.0 * Math.sin(increment) / (1.0 + Math.cos(increment)); } /** ======================================================================
11-06-2004

PUBLIC COMMENTS JVM crashes trying to draw very small Arc2D pie fraction when antialiasing is on. The crash seems to be due to endless recursion in libdcpr.so's processToRunsArc3().
10-06-2004