Java 我的方法是耗尽堆空间。是否需要将某些内容设置为null?
我创建了这个方法来以幻灯片形式显示图像列表。 它工作得很好,直到有超过50或60张图像需要处理。然后它崩溃了,伴随着Java 我的方法是耗尽堆空间。是否需要将某些内容设置为null?,java,animation,javafx,Java,Animation,Javafx,我创建了这个方法来以幻灯片形式显示图像列表。 它工作得很好,直到有超过50或60张图像需要处理。然后它崩溃了,伴随着 java.lang.OutOfMemoryError:java堆空间 所以我想知道我是否应该在每次循环中都将某个值设置为null?我在这里和网上搜索过,但没有找到答案 方法如下: private void createSlideshow(Stage stage, ArrayList<BufferedImage> slideList, int durationInSec
java.lang.OutOfMemoryError:java堆空间
所以我想知道我是否应该在每次循环中都将某个值设置为null?我在这里和网上搜索过,但没有找到答案
方法如下:
private void createSlideshow(Stage stage, ArrayList<BufferedImage> slideList, int durationInSecs) throws InterruptedException {
stage.show();
SequentialTransition slideshow = new SequentialTransition();
int i = 0;
for (BufferedImage bi: slideList) {
System.out.println(" Iteration " + (i++));
ImageView slide = new ImageView(SwingFXUtils.toFXImage(bi, null)); // LINE 108
FadeTransition fadeIn = new FadeTransition(Duration.millis(durationInSecs * 1000), slide);
fadeIn.setFromValue(0.0);
fadeIn.setToValue(1.0);
PauseTransition stayOn = new PauseTransition(Duration.millis(durationInSecs * 1000));
FadeTransition fadeOut = new FadeTransition(Duration.millis(durationInSecs * 1000), slide);
fadeOut.setFromValue(1.0);
fadeOut.setToValue(0.0);
SequentialTransition fadeInOut = new SequentialTransition();
fadeInOut.getChildren().addAll(fadeIn, stayOn, fadeOut);
slide.setOpacity(0.0);
root.getChildren().add(slide);
slideshow.getChildren().add(fadeInOut);
}
slideshow.play();
}
private void createSlideshow(Stage-Stage、ArrayList-slideList、int-durationInSecs)抛出InterruptedException{
stage.show();
SequentialTransition幻灯片放映=新的SequentialTransition();
int i=0;
用于(BuffereImage bi:slideList){
System.out.println(“迭代”+(i++);
ImageView幻灯片=新的ImageView(SwingFXUtils.toFXImage(bi,null));//第108行
FadeTransition fadeIn=新的FadeTransition(持续时间.millis(持续时间*1000),幻灯片);
fadeIn.setFromValue(0.0);
fadeIn.setToValue(1.0);
PauseTransition station=新的PauseTransition(持续时间.millis(持续时间*1000));
FadeTransition fadeOut=新的FadeTransition(持续时间.millis(持续时间*1000),幻灯片);
衰减。设置自值(1.0);
衰减设置值(0.0);
SequentialTransition fadeInOut=新的SequentialTransition();
fadeInOut.getChildren().addAll(fadeIn、stayOn、fadeOut);
幻灯片。设置不透明度(0.0);
root.getChildren().add(幻灯片);
slideshow.getChildren().add(fadeInOut);
}
slideshow.play();
}
完整的运行时消息如下所示:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.nio.HeapByteBuffer.<init>(Unknown Source)
at java.nio.ByteBuffer.allocate(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.createPlatformImage(Unknown Source)
at javafx.scene.image.Image.<init>(Unknown Source)
at javafx.scene.image.WritableImage.<init>(Unknown Source)
at javafx.embed.swing.SwingFXUtils.toFXImage(Unknown Source)
at Slideshow.createSlideshow(Slideshow.java:108)
at Slideshow.start(Slideshow.java:52)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source)
at com.sun.javafx.application.LauncherImpl$$Lambda$64/1581649247.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$49/1915503092.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$51/1557268138.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$50/1567581361.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$39/1645995473.run(Unknown Source)
... 1 more
Exception running application Slideshow
应用程序启动方法中出现异常
java.lang.reflect.InvocationTargetException
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(未知源)
在sun.reflect.DelegatingMethodAccessorImpl.invoke处(未知源)
位于java.lang.reflect.Method.invoke(未知源)
位于com.sun.javafx.application.LaunchImpl.launchApplicationWithArgs(未知源)
位于com.sun.javafx.application.LaunchImpl.launchApplication(未知源)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
位于sun.reflect.NativeMethodAccessorImpl.invoke(未知源)
在sun.reflect.DelegatingMethodAccessorImpl.invoke处(未知源)
位于java.lang.reflect.Method.invoke(未知源)
位于sun.launcher.launchelper$FXHelper.main(未知源)
原因:java.lang.RuntimeException:应用程序启动方法中的异常
位于com.sun.javafx.application.LaunchImpl.launchApplication1(未知源)
位于com.sun.javafx.application.launchempl.lambda$launchApplication$155(未知来源)
位于java.lang.Thread.run(未知源)
原因:java.lang.OutOfMemoryError:java堆空间
位于java.nio.HeapByteBuffer。(未知源)
位于java.nio.ByteBuffer.allocate(未知源)
在com.sun.javafx.tk.quantum.QuantumToolkit.createPlatformImage(未知源)
在javafx.scene.image.image。(未知源)
位于javafx.scene.image.WritableImage。(未知源)
位于javafx.embed.swing.SwingFXUtils.toFXImage(未知源)
在Slideshow.createSlideshow(Slideshow.java:108)中
在Slideshow.start(Slideshow.java:52)
位于com.sun.javafx.application.launchempl.lambda$launchApplication1$162(未知来源)
位于com.sun.javafx.application.launchempl$$Lambda$64/1581649247.run(未知源)
com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(未知来源)
位于com.sun.javafx.application.PlatformImpl$$Lambda$49/1915503092.run(未知来源)
位于com.sun.javafx.application.PlatformImpl.lambda$null$173(未知来源)
位于com.sun.javafx.application.PlatformImpl$$Lambda$51/1557268138.run(未知源)
位于java.security.AccessController.doPrivileged(本机方法)
com.sun.javafx.application.PlatformImpl.lambda$runLater$174(未知来源)
位于com.sun.javafx.application.PlatformImpl$$Lambda$50/1567581361.run(未知来源)
在com.sun.glass.ui.InvokeLaterDispatcher$Future.run(未知源)
在com.sun.glass.ui.win.WinApplication.\u runLoop(本机方法)
在com.sun.glass.ui.win.WinApplication.lambda$null$148(未知来源)
在com.sun.glass.ui.win.WinApplication$$Lambda$39/1645995473.run(未知来源)
... 还有一个
运行应用程序幻灯片时出现异常
您的主
顺序转换
正在加载所有图像,并在开始播放之前保留对它们的引用。因此,这种技术不会随着图像数量的增加而扩展(这意味着,如果您有足够的图像,就一定会耗尽堆空间)
如果您的图像从BufferedImage
s合理快速地转换为FXImage
s,您可以使用时间线来执行此操作:
private void createSlideshow(Stage stage, ArrayList<BufferedImage> slideList, int durationInSecs) throws InterruptedException {
stage.show();
Timeline slideshow = new Timeline();
ImageView slide = new ImageView();
for (int i = 0; i < slideList.size(); i++) {
BufferedImage bi = slideList.get(i);
KeyFrame newImageFrame = new KeyFrame(Duration.seconds(durationInSeconds * 3 * i), e ->
slide.setImage(SwingFXUtils.toFXImage(bi, null)));
KeyFrame startFadeIn = new KeyFrame(Duration.seconds(durationInSeconds * 3 * i),
new KeyValue(slide.opacityProperty(), 0));
KeyFrame endFadeIn = new KeyFrame(Duration.seconds(durationsInSeconds * (3 * i + 1)),
new KeyValue(slide.opacityProperty(), 1));
KeyFrame startFadeOut = new KeyFrame(Duration.seconds(durationInSeconds * (3 * i + 2)),
new KeyValue(slide.opacityProperty(), 1));
slideshow.getKeyFrames().addAll(newImageFrame, startFadeIn, endFadeIn, startFadeOut);
}
slideshow.play();
}
最后请注意,您的原始代码以及这两种实现都希望将
buffereImage
s列表传递给该方法。这已经消耗了大量内存:在进入方法体之前,您基本上将所有图像都保存在内存中。根据这些图像的来源,例如,您可以传递文件
对象的列表,并在此处使用相同的技术根据需要动态加载每个图像(或创建一个小的图像队列,如第二个示例所示)。这实际上可以扩展到任意数量的图像。可能您没有足够的堆来容纳正在加载的图像。注意:执行此操作时,图像将被解压缩,因此将使用其完全未压缩的大小。e、 g.一张200万像素的图像可能会使用8MB的32位彩色图像,如果
private void createSlideshow(Stage stage, ArrayList<BufferedImage> slideList, int durationInSecs) throws InterruptedException {
stage.show();
int numImages = slideList.size();
BlockingQueue<Image> images = new ArrayBlockingQueue<>(3);
Thread conversionThread = new Thread(() -> {
for (BufferedImage bi : slideList) {
try {
images.put(SwingFXUtils.toFXImage(bi, null));
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
}
});
conversionThread.setDaemon(true);
conversionThread.start();
Timeline slideshow = new Timeline();
ImageView slide = new ImageView();
for (int i = 0; i < slideList.size(); i++) {
KeyFrame newImageFrame = new KeyFrame(Duration.seconds(durationInSeconds * 3 * i), e ->
slide.setImage(images.poll()));
KeyFrame startFadeIn = new KeyFrame(Duration.seconds(durationInSeconds * 3 * i),
new KeyValue(slide.opacityProperty(), 0));
KeyFrame endFadeIn = new KeyFrame(Duration.seconds(durationsInSeconds * (3 * i + 1)),
new KeyValue(slide.opacityProperty(), 1));
KeyFrame startFadeOut = new KeyFrame(Duration.seconds(durationInSeconds * (3 * i + 2)),
new KeyValue(slide.opacityProperty(), 1));
slideshow.getKeyFrames().addAll(newImageFrame, startFadeIn, endFadeIn, startFadeOut);
}
slideshow.play();
}