环境:
JDK: 1.8u112 oracle
JRE: 10.0.2
JVM最大堆大小:~2 2GB。
操作系统: Windows 10
IDE: Netbeans 8.1
RAM: DDR4 8 8GB
处理器: 6700hq i7英特尔
Context
一个简单的GUI,它打开一个图像文件(jpg/png),并通过用户输入放大它。
描述
类扩展了JFrame。框架的contentPane有一个JButton、一个JLabel和一个JScrollPane。单击该按钮将显示一个JFileChooser。标签在滚动窗格内。选择一个文件将在标签中打开它(仅在此问题中打开图像文件-在其上测试jpg/png)。标签有一个鼠标滚轮监听器,可以通过Image.getScaledInstance
缩放图像。每次缩放时,都会打印放大动作(新图像宽度(或高度)与相应原始图像宽度(或高度)的比率)和Runtime.totalMemory
。
Problem
ImageIcon
对象(参见代码)不会被gced吗?代码
import java.awt.Dimension;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class gui extends javax.swing.JFrame {
Image image;
Dimension size;
private double mag = 1;
Runtime runtime = Runtime.getRuntime();
public gui() {
initComponents();
}
private void zoom() {
int[] newSize = {(int) (size.width * mag), (int) (size.height * mag)};
if (newSize[0] > 0 && newSize[1] > 0) {
label.setIcon(new ImageIcon(image.getScaledInstance(newSize[0], newSize[1], Image.SCALE_DEFAULT)));
}
System.out.println("mag:" + (int) (mag * 100) + "% mem:" + runtime.totalMemory() / 1024 / 1024 + "MB");
}
private void loadImage(File imgFile) throws IOException {
String path = imgFile.getPath().toLowerCase();
if (path.endsWith("gif")) {
ImageIcon icon = new ImageIcon(path);
image = icon.getImage();
label.setIcon(icon);
} else {
image = ImageIO.read(imgFile);
ImageIcon icon = new ImageIcon(image);
label.setIcon(icon);
}
size = new Dimension(image.getWidth(null), image.getHeight(null));
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
dialog = new javax.swing.JFileChooser();
jScrollPane1 = new javax.swing.JScrollPane();
label = new javax.swing.JLabel();
button = new javax.swing.JButton();
dialog.setCurrentDirectory(new java.io.File("D:\\"));
dialog.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
dialogActionPerformed(evt);
}
});
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Image Viewer");
label.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
label.setVerticalAlignment(javax.swing.SwingConstants.TOP);
label.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
labelMouseWheelMoved(evt);
}
});
jScrollPane1.setViewportView(label);
button.setText("open");
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 689, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(button)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(button)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 430, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>
private void dialogActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
if (evt.getActionCommand().equals(JFileChooser.APPROVE_SELECTION)) {
try {
File file = dialog.getSelectedFile();
loadImage(file);
setTitle(file.getPath());
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private void labelMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
if (image != null) {
int amt = -evt.getWheelRotation();
double newMag = mag + amt * 0.1;
if (newMag > 0) {
mag = newMag;
zoom();
}
}
}
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
dialog.showOpenDialog(this);
}
public static void main(String args[]) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new gui().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton button;
private javax.swing.JFileChooser dialog;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel label;
// End of variables declaration
}
测试文件
除了test file之外,任何jpg或png图像都应该可以。
测试文件的输出
mag:110%内存:123MB内存:120%内存:123MB内存:130%内存:123MB内存:150%内存:123MB内存:160%内存:123MB内存:150%内存:123MB内存:160%内存:123MB内存:160MB内存:123MB内存:170%内存:123MB内存:180%内存:155MB内存:190%内存:155MB内存:200%内存:155MB内存:220%内存:155MB内存:230%内存:157MB内存:240%内存:157MB内存:250%内存:157MB内存:260%mem:157MB mag: 270%mem:253MB mag:280%mem:253MB mag:230%mem:253MB mag:300%mem:253MB mag:310%mem:256MB mag:330%mem:256MB mag:340%mem:256MB mag:350%mem:256MB mag:360%mem:256MB mag:370%mem:393MB mag:390%mem:393MB mag:390%mem:393MB mag:393MB mag:410%mem:393MB mag:420%mem:393MB mag:430%内存:466MB内存:440%内存:466MB内存:460%内存:466MB内存:470%内存:466MB内存:480%内存:466MB内存:489%内存:541MB内存:499%内存:541MB内存:509%内存:541MB内存:519%内存:541MB内存:529%内存:541MB内存:539%内存:641MB内存:549%内存:641MB内存:559%内存:641MB内存:569%mem:641MB内存:579%mem:641MB内存:589%mem:825MB内存:599% mem:825MB mag:609%mem:825MB mag:619%mem:825MB mag:629%mem:892MB mag:639%mem:892MB mag:649%mem:892MB mag:659%mem:892MB mag:669%mem:892MB mag:679%mem:689%mem:881MB mag:699%mem:881MB mag:709%mem:881MB mag:719%mem:881MB mag:729%mem:1029MB mag:739%mem:1029MB mag:749%mem内存:1029MB内存:759%内存:1029MB内存:769%内存:1104MB内存:779%内存:1104MB内存:789%内存:1104MB内存:799%内存:1104MB内存:809%内存:1075MB内存:819%内存:1075MB内存:829%内存:1075MB内存:839%内存:1182MB内存:1182MB内存:859%内存:1182MB内存:869%内存:1289MB内存:879%mem:1289MB内存:889%mem:154MB内存:899%mem:154MB内存:909%mem:152MB内存:919%mem:1569MB内存:929%内存:1569MB内存:939%内存:1569MB内存:949%内存:1480MB内存:959%内存:1480MB内存:969%内存:1548MB内存:979%内存:1548MB内存:989%内存:1655MB内存:999%内存:1655MB内存:1009%内存:1707MB内存:1019%内存:1707MB内存:1029%内存:1802MB内存:1039%内存:1850MB内存:1049%mem:1850MB内存:1059%mem:1871MB内存:1069%mem:1871MB内存:1079%mem:1801MB内存1862MB磁盘盒:1099%内存:1862MB磁盘盒:1109%mem:1815MB磁盘盒:1119%mem:1822MB磁盘盒:1129%mem:1758MB磁盘盒:1139%mem:1774MB磁盘盒:1149%mem:1711MB磁盘盒:1159%mem:1734MB磁盘盒:1169%mem:1676MB磁盘盒:1179%mem:1708MB磁盘盒:1189%mem:1654MB
发布于 2018-08-25 06:23:37
丢弃的ImageIcon对象(参见代码)不会被gced吗?
在GC不运行的情况下,如何对它们进行GC?
当内存足够时,为什么要运行GC?
就这样。GC在需要的时候运行,通过将内存使用量保持在不必要的水平并不会带来太大的好处。
出于效率的原因,GC实际上是一个“幸存收集器”:它只处理幸存的对象,留下的是空闲内存。因此,运行它是有意义的,因为大多数对象在年轻时就会死亡。
预期的
应在11.8*11.8*7.23KB的量级左右
不,Java进程可以自由地使用您给它的所有内存。
缩小时,内存消耗不会减少
是的,因为GC不需要运行。
为什么堆这么大(大约17倍于mag,达到2 2GB)
所有中等大小的图像都无法访问,但尚未收集。
在mag * mag *originalImageSize(以字节为单位)小于50%jvm最大堆大小的情况下,如何使代码适用于mag?
当Java进程需要内存时,它就会被回收。
我说了点小谎话。您可以手动调用System.gc
,它可能会有所帮助。但不要这么做。虽然这回答了最后一个问题,但它并没有解决真正的问题。如果您想保持较低的内存使用率,那么可以使用-Xmx1000M
或类似的方法来减少内存使用量。
https://stackoverflow.com/questions/51999393
复制相似问题