-
Bug
-
Resolution: Unresolved
-
P4
-
8, 9
-
generic
-
generic
FULL PRODUCT VERSION :
I've confirmed:
java 9.0.1
java 1.8.0_144
ADDITIONAL OS VERSION INFORMATION :
I've confirmed this exception in:
Windows 7 32bit
Windows 7 64bit
Windows 10 64bit
MacOS 10.13.1
EXTRA RELEVANT SYSTEM CONFIGURATION :
This report has no relationship about network or some other devices.
The reported bug occurs in PC independently.
A DESCRIPTION OF THE PROBLEM :
I'd like to realize a video player by using JavaFX, and I know there are several JavaFX video players with file loading, but I 'd like to watch the video from byte[] to JavaFX Image for some reasons.
As long as I know, WritableImage and PixelWriter#setPixels() are the only way to realize what I want to.
When I use a ImageView, there is no problems.
However, when I use some ImageViews, so many exceptions such as NullPointerException, java.lang.IndexOutOfBoundsException occur in JavaFX.
The exceptions are shown the below of this description.
To avoid the exceptions, I found WritableImage must be renewed every time.
I wonder if this is a bug of JavaFX or specification.
Finally, I made a minimum bug occurring source code.
So I'd like you to check by using that code.
Exception example:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
REGRESSION. Last worked in version 8u144
ADDITIONAL REGRESSION INFORMATION:
Java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot (TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. WritableImage instance is initialized
WritableImage wi = new WritableImage(width, height)
2. fill in the image data into byte[]
byte[] data = fillInData()
3. write pixel data from byte[] into WritableImage
wi.getPixelWriter().setPixels(0, 0, width, height, pf, data, 0, width*3)
4. set WritableImage to ImageView
imageView.setImage(wi)
5. loop from 2
I got an error in step 4.
The content of error depends on a case.
For example, like below:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
To avoid an error, before step 3 in above, renew WritableImage instance.
wi = new WritableImage(width, height)
My expected result is no need to renew.
Or is this a specification of JavaFX?
ACTUAL -
The exception example:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
there is no crash log.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* WritableImage test code
*/
public class WritableImageTest extends Application {
// If false, some Exception occurs and GUI refresh stops.
// To avoid Exception, this flag must be set to true.
boolean exceptionAvoidFlag = false;
@Override
public void start(Stage primaryStage) throws Exception {
VBox vBox = new VBox();
ArrayList<UpdateTask> tasks = new ArrayList<>();
for (int i = 0; i < 50; i++) {
UpdateTask task = new UpdateTask(i);
tasks.add(task);
vBox.getChildren().add(createBp(task));
}
tasks.forEach(t -> new Thread(t).start());
Scene scene = new Scene(vBox, 400, 600);
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(v -> tasks.forEach(t -> t.stop = true));
primaryStage.show();
}
/**
* create BorderPane with Label and ImageView
*/
BorderPane createBp(UpdateTask task) {
final BorderPane borderPane = new BorderPane();
final Label label = new Label("update info...");
final ImageView imageView = new ImageView();
task.valueProperty().addListener((ob, o, n) -> {
if (n == null) return;
label.setText(n.labelStr);
imageView.setImage(n.image);
});
borderPane.setTop(label);
borderPane.setCenter(imageView);;
return borderPane;
}
/**
* main entry point
*/
public static void main(String args[]) {
launch(args);
}
/**
* update label info and image
*/
class UpdateTask extends Task<UpdateInfo> {
boolean stop = false;
int id;
int width = 320, height = 240;
public UpdateTask(int _id) {
id = _id;
}
@Override
protected UpdateInfo call() throws Exception {
int ctr = 0;
byte[] data = new byte[width * height * 3];
WritableImage wi = new WritableImage(width, height);
PixelFormat<ByteBuffer> pf = PixelFormat.getByteRgbInstance();
while (!stop) {
String str = id+" update: "+ctr;
// TODO need to renew WritableImage instance in order to avoid NLE
if (exceptionAvoidFlag) wi = new WritableImage(width, height);
fillImage(wi, pf, ctr++, data);
updateValue(new UpdateInfo(str, wi));
Thread.sleep(50);
}
return null;
}
/**
* fill in arbitrary data and write into WritableImage
*/
private void fillImage(WritableImage wi, PixelFormat<ByteBuffer> pf, int index, byte[] data) {
for (int i = 0; i < data.length; i+=3) {
data[i + 0] = (byte) (i + index * 3);
data[i + 1] = (byte) (i + index * 3);
data[i + 2] = (byte) (i + index * 3);
}
wi.getPixelWriter().setPixels(0, 0, width, height, pf, data, 0, width * 3);
}
}
/**
* update info
*/
class UpdateInfo {
String labelStr;
Image image;
public UpdateInfo(String s, Image i) {
labelStr = s;
image = i;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Same as Expected Result.
I've confirmed:
java 9.0.1
java 1.8.0_144
ADDITIONAL OS VERSION INFORMATION :
I've confirmed this exception in:
Windows 7 32bit
Windows 7 64bit
Windows 10 64bit
MacOS 10.13.1
EXTRA RELEVANT SYSTEM CONFIGURATION :
This report has no relationship about network or some other devices.
The reported bug occurs in PC independently.
A DESCRIPTION OF THE PROBLEM :
I'd like to realize a video player by using JavaFX, and I know there are several JavaFX video players with file loading, but I 'd like to watch the video from byte[] to JavaFX Image for some reasons.
As long as I know, WritableImage and PixelWriter#setPixels() are the only way to realize what I want to.
When I use a ImageView, there is no problems.
However, when I use some ImageViews, so many exceptions such as NullPointerException, java.lang.IndexOutOfBoundsException occur in JavaFX.
The exceptions are shown the below of this description.
To avoid the exceptions, I found WritableImage must be renewed every time.
I wonder if this is a bug of JavaFX or specification.
Finally, I made a minimum bug occurring source code.
So I'd like you to check by using that code.
Exception example:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
REGRESSION. Last worked in version 8u144
ADDITIONAL REGRESSION INFORMATION:
Java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot (TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. WritableImage instance is initialized
WritableImage wi = new WritableImage(width, height)
2. fill in the image data into byte[]
byte[] data = fillInData()
3. write pixel data from byte[] into WritableImage
wi.getPixelWriter().setPixels(0, 0, width, height, pf, data, 0, width*3)
4. set WritableImage to ImageView
imageView.setImage(wi)
5. loop from 2
I got an error in step 4.
The content of error depends on a case.
For example, like below:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
To avoid an error, before step 3 in above, renew WritableImage instance.
wi = new WritableImage(width, height)
My expected result is no need to renew.
Or is this a specification of JavaFX?
ACTUAL -
The exception example:
Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 48
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:440)
at javafx.graphics/javafx.scene.Parent.updateCachedBounds(Parent.java:1723)
at javafx.graphics/javafx.scene.Parent.recomputeBounds(Parent.java:1667)
at javafx.graphics/javafx.scene.Parent.doComputeGeomBounds(Parent.java:1520)
at javafx.graphics/javafx.scene.Parent.access$200(Parent.java:81)
at javafx.graphics/javafx.scene.Parent$1.doComputeGeomBounds(Parent.java:117)
at javafx.graphics/com.sun.javafx.scene.ParentHelper.computeGeomBoundsImpl(ParentHelper.java:86)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBoundsImpl(RegionHelper.java:78)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.superComputeGeomBounds(RegionHelper.java:62)
at javafx.graphics/javafx.scene.layout.Region.doComputeGeomBounds(Region.java:3291)
at javafx.graphics/javafx.scene.layout.Region.access$300(Region.java:149)
at javafx.graphics/javafx.scene.layout.Region$1.doComputeGeomBounds(Region.java:170)
at javafx.graphics/com.sun.javafx.scene.layout.RegionHelper.computeGeomBoundsImpl(RegionHelper.java:89)
at javafx.graphics/com.sun.javafx.scene.NodeHelper.computeGeomBounds(NodeHelper.java:117)
at javafx.graphics/javafx.scene.Node.updateGeomBounds(Node.java:3831)
at javafx.graphics/javafx.scene.Node.getGeomBounds(Node.java:3793)
at javafx.graphics/javafx.scene.Node.getLocalBounds(Node.java:3741)
at javafx.graphics/javafx.scene.Node.updateTxBounds(Node.java:3895)
at javafx.graphics/javafx.scene.Node.getTransformedBounds(Node.java:3687)
at javafx.graphics/javafx.scene.Node.updateBounds(Node.java:766)
at javafx.graphics/javafx.scene.Parent.updateBounds(Parent.java:1851)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2522)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:410)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:409)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:436)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:518)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:498)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:491)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:319)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
there is no crash log.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.nio.ByteBuffer;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* WritableImage test code
*/
public class WritableImageTest extends Application {
// If false, some Exception occurs and GUI refresh stops.
// To avoid Exception, this flag must be set to true.
boolean exceptionAvoidFlag = false;
@Override
public void start(Stage primaryStage) throws Exception {
VBox vBox = new VBox();
ArrayList<UpdateTask> tasks = new ArrayList<>();
for (int i = 0; i < 50; i++) {
UpdateTask task = new UpdateTask(i);
tasks.add(task);
vBox.getChildren().add(createBp(task));
}
tasks.forEach(t -> new Thread(t).start());
Scene scene = new Scene(vBox, 400, 600);
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(v -> tasks.forEach(t -> t.stop = true));
primaryStage.show();
}
/**
* create BorderPane with Label and ImageView
*/
BorderPane createBp(UpdateTask task) {
final BorderPane borderPane = new BorderPane();
final Label label = new Label("update info...");
final ImageView imageView = new ImageView();
task.valueProperty().addListener((ob, o, n) -> {
if (n == null) return;
label.setText(n.labelStr);
imageView.setImage(n.image);
});
borderPane.setTop(label);
borderPane.setCenter(imageView);;
return borderPane;
}
/**
* main entry point
*/
public static void main(String args[]) {
launch(args);
}
/**
* update label info and image
*/
class UpdateTask extends Task<UpdateInfo> {
boolean stop = false;
int id;
int width = 320, height = 240;
public UpdateTask(int _id) {
id = _id;
}
@Override
protected UpdateInfo call() throws Exception {
int ctr = 0;
byte[] data = new byte[width * height * 3];
WritableImage wi = new WritableImage(width, height);
PixelFormat<ByteBuffer> pf = PixelFormat.getByteRgbInstance();
while (!stop) {
String str = id+" update: "+ctr;
// TODO need to renew WritableImage instance in order to avoid NLE
if (exceptionAvoidFlag) wi = new WritableImage(width, height);
fillImage(wi, pf, ctr++, data);
updateValue(new UpdateInfo(str, wi));
Thread.sleep(50);
}
return null;
}
/**
* fill in arbitrary data and write into WritableImage
*/
private void fillImage(WritableImage wi, PixelFormat<ByteBuffer> pf, int index, byte[] data) {
for (int i = 0; i < data.length; i+=3) {
data[i + 0] = (byte) (i + index * 3);
data[i + 1] = (byte) (i + index * 3);
data[i + 2] = (byte) (i + index * 3);
}
wi.getPixelWriter().setPixels(0, 0, width, height, pf, data, 0, width * 3);
}
}
/**
* update info
*/
class UpdateInfo {
String labelStr;
Image image;
public UpdateInfo(String s, Image i) {
labelStr = s;
image = i;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Same as Expected Result.
- relates to
-
JDK-8163078 ArrayIndexOutOfBounds is thrown in Parent.updateCachedBounds
-
- Open
-