ChartViewer crashes JavaFX in case of multiple threads

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
darksnake
Posts: 3
Joined: Sat May 14, 2016 1:23 pm
antibot: No, of course not.

ChartViewer crashes JavaFX in case of multiple threads

Post by darksnake » Sat May 14, 2016 3:46 pm

I am using JFreeChart inside JavaFX application. Currently I am using SwingNode to embed chart inside JavaFX scene but there are some unpleasant lags during node re-size so I am trying to migrate to ChartViewer. It works fine for static plots, but it produces random crashes when I am trying to make a lot of dynamic changes simultaneously (for example, I have about 100 line plots in one chart window and I am changing their parameters).
Sometimes it just throws exceptions and stops whatever it is doing, but sometimes it just crashes the whole JavaFX framework. It produces a lot of different errors at random, but the most frequent ones are:

Code: Select all

java.lang.InternalError: Unrecognized PGCanvas token: 66

Code: Select all

java.lang.InternalError: Unrecognized PGCanvas token: 67
and

Code: Select all

java.nio.BufferOverflowException
	at com.sun.javafx.sg.prism.GrowableDataBuffer.ensureReadCapacity(GrowableDataBuffer.java:317)
I believe such problems are usually connected with multithreading problems, but all my calls to JFreeChart API are synchronized and wrapped in Platform.runLater(). The problem exists both for latest JfreeChart (1.5.0- SNAPSHOT) and fse editions.

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by david.gilbert » Sun May 15, 2016 7:05 am

I'm interested to get to the bottom of this one, so if you can post some more details it would be great. Which JDK platform and version are you using? Are your charts particularly large or complex? Any chance of the sample program that reproduces the problem?

Does it help if you increase the heap size for the JVM? The BufferOverflowException I have seen before, but that was due to the Canvas never being cleared so all drawing operations were accumulating...that bug was fixed earlier and you're still seeing this issue with the latest code so I don't think that is it.

Anyone else running into the same problem?
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

darksnake
Posts: 3
Joined: Sat May 14, 2016 1:23 pm
antibot: No, of course not.

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by darksnake » Sun May 15, 2016 11:51 am

I am running latest Oracle JDK (8u92) under windows 10.
My aim is to work with pretty large charts (currently 100 line plots with 4000 data points in each), but it should not reach memory cap. It usually loads, but when I try to, for example, turn all lines invisible, it crashes somewhere in the middle of the process (turns invisible half of the lines and than turns unresponsive).
Also I have a small testing example which contains only two plots with about 10 points. It load and works fine, but when I try to turn visibility on and off and turn other display parameters fast enough, it crashes randomly.

Sadly, I can not extract my example itself, because it requires a framework around it (and it is quite heavy for this task), but I will try to make a short stand-alone test example.

darksnake
Posts: 3
Joined: Sat May 14, 2016 1:23 pm
antibot: No, of course not.

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by darksnake » Sun May 15, 2016 1:32 pm

While preparing the example, I found the source of the problem. There was a hidden call to the API from non-UI thread in my framework. When I fixed it, everything started to work as expected. Normally, JavaFX throws an exception if calls are made from non-UI thread. Is it possible to add this check to JFreeChart?

Since I've made an example, here is the link: https://bitbucket.org/snippets/Altavir/46q64 . It is working as expected.

plusik
Posts: 28
Joined: Tue May 16, 2006 3:36 am
Location: Boston, MA, USA

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by plusik » Tue May 24, 2016 5:05 pm

+1 for adding the checks to JFreeChart if calls are made on JavaFX thread

HandsOfStone
Posts: 3
Joined: Tue Sep 26, 2017 2:55 pm
antibot: No, of course not.

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by HandsOfStone » Thu Oct 12, 2017 4:53 pm

I am also running into this problem when using ChartViewer.

John Matthews
Posts: 513
Joined: Wed Sep 12, 2007 3:18 pm

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by John Matthews » Fri Oct 13, 2017 11:03 am

You can use Platform.isFxApplicationThread to determine if "a given task is being executed…on the JavaFX Application Thread." Although convenient for precluding some common errors, such a check is no panacea; it is your application's responsibility to ensure that GUI elements are accessed and modified only from the JavaFX Application thread. See Concurrency in JavaFX for additional design guidance.

rodry543
Posts: 1
Joined: Mon Jan 13, 2020 9:30 am
antibot: No, of course not.

Re: ChartViewer crashes JavaFX in case of multiple threads

Post by rodry543 » Mon Jan 13, 2020 9:45 am

A simple solution for Multiple Threads in JavaFX (a Timer in JavaFX to refresh a chart periodly, for example) could be these:

Code: Select all

	public void initialize() {
		XYDataset dataset = createDataset();
		JFreeChart chart = createChart(dataset);
		chartViewer.setChart(chart);

		Timer timer = new java.util.Timer();

		timer.schedule(new TimerTask() {
			public void run() {
				Platform.runLater(new Runnable() {
					public void run() {
// START YOUR TIMER CODE
						System.err.println("timer pulse");

						if (chartValuesL.getItemCount() >= 10) {
							chartValuesL.delete(0, 0);
						}
						if (chartValuesH.getItemCount() >= 10) {
							chartValuesH.delete(0, 0);
						}

						Second t = new Second();
						
						chartValuesL.add(t, randNum());
						chartValuesH.add(t, randNum());
						//
						System.out.println(chartValuesH.getItemCount());
						//
						while (chartValuesL.getItemCount() < 2 || chartValuesH.getItemCount() < 2) {
							chartValuesL.add(t.next().next(), randNum());
							chartValuesH.add(t.next().next(), randNum());
						}
// END YOUR TIMER CODE
					}
				});

			}
		}, 3500, 3500);
	}
The most important code here is

Code: Select all

Platform.runLater(new Runnable() {.....});
that runs the new thread in a subprocces of JavaFX thread.

Locked