环境:
JDK:1.8u112甲骨文
JRE:10.0.2
JVM最大堆大小:〜2GB。
操作系统:Windows 10
IDE:Netbeans 8.1
RAM:DDR4 8GB
处理器:6700hq i7英特尔
上下文
一个简单的GUI,可以打开图像文件(jpg / png)并通过用户输入将其放大。
描述
一个类扩展了JFrame。框架的contentPane具有JButton,JLabel和JScrollPane。单击该按钮将显示一个JFileChooser。标签在滚动窗格内。选择一个文件将在标签中将其打开(仅出于测试此问题jpg / png的目的打开图像文件)。标签具有鼠标滚轮监听器,可通过Image.getScaledInstance
缩放图像。每次缩放时,都会打印放大倍率(新图像宽度(或高度)与相应原始图像的比率)和Runtime.totalMemory
。
问题
ImageIcon
个对象(请参见代码)?代码
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%mem:123MB mag:120%mem:123MB mag:130%mem:123MB mag:140%mem:123MB mag:150%mem:123MB mag:160%mem:123MB mag:150%mem:123MB mag:160%mem:123MB mag:170%mem:123MB 大小:180%内存:155MB 大小:190%内存:155MB 大小:200%内存:155MB mag:210%mem:155MB 大小:220%内存:155MB mag:230%mem:157MB mag:240%mem:157MB mag:250%mem:157MB 大小:260%内存:157MB mag:270%mem:253MB mag:280%mem:253MB mag:290%mem:253MB mag:300%mem:253MB mag:310%mem:253MB mag:320%mem:256MB mag:330%mem:256MB mag:340%mem:256MB mag:350%mem:256MB mag:360%mem:256MB 大小:370%内存:393MB 大小:380%内存:393MB mag:390%mem:393MB mag:400%mem:393MB 大小:410%内存:393MB mag:420%mem:393MB mag:430%mem:466MB mag:440%mem:466MB mag:450%mem:466MB mag:460%mem:466MB mag:470%mem:466MB mag:480%mem:466MB mag:489%mem:541MB mag:499%mem:541MB mag:509%mem:541MB mag:519%mem:541MB mag:529%mem:541MB mag:539%mem:641MB mag:549%mem:641MB mag:559%mem:641MB mag:569%mem:641MB mag:579%mem:641MB mag:589%mem:825MB mag:599%mem:825MB mag:609%mem:825MB mag:619%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:892MB mag: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 mag:759%mem:1029MB 大小:769%内存:1104MB mag:779%mem:1104MB mag:789%mem:1104MB mag:799%mem:1104MB mag:809%mem:1075MB mag:819%mem:1075MB mag:829%mem:1075MB mag:839%mem:1182MB mag:849%mem:1182MB mag:859%mem:1182MB mag:869%mem:1289MB mag:879%mem:1289MB mag:889%mem:1542MB mag:899%mem:1542MB mag:909%mem:1542MB mag:919%mem:1569MB mag:929%mem:1569MB mag:939%mem:1569MB 大小:949%内存:1480MB mag:959%mem:1480MB 大小:969%内存:1548MB mag:979%mem:1548MB 大小:989%内存:1655MB 大小:999%内存:1655MB mag:1009%mem:1707MB mag:1019%mem:1707MB mag:1029%mem:1802MB mag:1039%mem:1850MB mag:1049%mem:1850MB mag:1059%mem:1871MB mag:1069%mem:1871MB mag:1079%mem:1801MB mag:1089%mem:1862MB mag:1099%mem:1862MB mag:1109%mem:1815MB mag:1119%mem:1822MB mag:1129%mem:1758MB mag:1139%mem:1774MB mag:1149%mem:1711MB mag:1159%mem:1734MB mag:1169%mem:1676MB mag:1179%mem:1708MB mag:1189%mem:1654MB
答案 0 :(得分:0)
丢弃的ImageIcon对象(请参见代码)是否未设置大小?
如何在不运行GC的情况下对它们进行GC处理?
当内存足够时为什么要运行GC?
就是这样。 GC会在需要时运行,并且通过将内存使用率保持在低于必要水平来赢不了多少。
出于效率方面的考虑,GC实际上是一个“幸存者收集器”:它仅处理幸存的对象,而剩下的是可用内存。因此,在大多数对象都年轻时就将其运行为ALAP是有意义的。
预计应为11.8 * 11.8 * 7.23KB左右
不,Java进程可以自由使用您为其分配的所有内存。
缩小时,内存消耗不会减少
是的,因为无需运行GC。
为什么堆会这么大地扩展(约为磁石的17倍,达到2GB)
所有中间尺寸的图像均无法访问,但尚未收集。
在mag * mag * originalImageSize(以字节为单位)<50%JVM最大堆大小的情况下,如何使代码对mag可行?
不能。当Java进程需要内存时,它将被回收。
我在撒谎。您可以手动致电System.gc
,这可能会有所帮助。但是不要这样做。虽然这回答了最后一个问题,但没有解决任何实际问题。如果要保持较低的内存使用量,请使用-Xmx1000M
或类似方法为Java减少内存用量。