如何从内存中删除变量?
How to delete variable from memory?
将文件转换为字节时,不应使用 Files.readAllBytes class。
使用不同的字节转换器后。主要问题是变量中的byte数组无法从内存中删除
示例 1
byte[] x1=new byte[50];
x1=null; //not memory deleting;
示例 2
byte[] x2=null; //memory space:0
x2=new byte[50]; //memory space:50
x2=new byte[100]; //memory space:150
x2=new byte[10]; //memory space:160
x2=null; //memory space:160
我意识到情况就是这样。
我们如何从内存中清除它 space?
C语言中有动态内存分配方法(Malloc),java.
中没有删除这块内存
package dragdrop;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class gfgh {
private JFrame frame;
private File_Class file_Class=null;
private JPanel panel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
gfgh window = new gfgh();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public gfgh() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setBackground(Color.BLACK);
frame.getContentPane().add(panel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
memorydelete();
}
});
panel.add(btnNewButton);
this.DragDrop(panel);
}
private void DragDrop(JComponent component)
{
@SuppressWarnings("serial")
TransferHandler transferHandler=new TransferHandler(){
@Override
public boolean canImport(JComponent component,DataFlavor[] dataFlavor)
{
return true;
}
@SuppressWarnings("unchecked")
@Override
public boolean importData(JComponent comp, Transferable t) {
// TODO Auto-generated method stub
List<File> files;
try {
files = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
for(File file:files)
{
System.out.println(file.getAbsolutePath());
System.out.println(file.length());
file_Class=new File_Class();
//file read examle 1 false
// file_Class.file=Files.readAllBytes(Paths.get(file.getAbsolutePath()));
//* file read example 2 false
/*
RandomAccessFile f = new RandomAccessFile(file.getAbsolutePath(), "r");
file_Class.file = new byte[(int)f.length()];
f.readFully( file_Class.file);
*/
//example 3 false
// file_Class.file=readFile(file);
//example 4 false
file_Class.file=readFile(file);
memorydelete();
///////
}
files=null;
Runtime.getRuntime().gc();
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
};
component.setTransferHandler(transferHandler);
}
public void memorydelete()
{
file_Class.file=null;
file_Class=null;
Runtime.getRuntime().gc();
}
public static byte[] readFile(File file) throws IOException {
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
} finally {
f.close();
}
}
}
class File_Class {
public byte file[];
}
The main problem is that the byte array in the variable cannot be deleted from memory.
没有。这不是问题。
您需要做的就是通过将 null
分配给变量来安排字节数组不可访问...以及任何其他仍保留对数组的引用的可访问变量。
垃圾收集器 (GC) 会处理它。
您不需要致电 System.gc()
。 GC 将在需要 运行 时 运行。如果您尝试干预,您可能只会使您的代码效率低下。
参见:Why is it bad practice to call System.gc()?
真正的问题是以下之一:
文件太大无法读入内存;即大到你得到一个 OOME。如果是这种情况,解决方案是流式传输文件而不是使用 readAllBytes
.
您着迷于内存利用率。内存很便宜。程序员的时间是昂贵的。
如果您确实需要 最大限度地减少应用程序的内存使用,那么您使用了错误的编程语言。 Java 不是为这种编程风格设计的。 Java 和 Java 垃圾收集器被设计为在 GC 运行 不频繁并且有足够的空闲内存在收集之间保存垃圾的情况下高效。如果您试图解决这个问题,您的应用程序很可能会浪费大量时间来回收少量内存。
请注意,即使 Java GC 确实(几乎)立即收集了您无法访问的字节数组,它也可能不会 return 回收内存给操作系统。所以你的应用程序的内存占用不会缩小。所以你很可能不会从显式调用 System.gc()
中获得 任何 真正的好处。
如果你确实需要来最小化内存使用量,请使用 C 或 C++
如果你确实需要显式删除对象,请使用 C 或 C++
在Java中,数组是对象。 Java 垃圾收集器最终会处理它们并回收与未引用对象关联的内存。
您可以按如下方式轻松测试:
public class Test {
public static void main(String[] args) {
long m1 = Runtime.getRuntime().freeMemory();
byte[] data = new byte[1024*1024*4];
long m2 = Runtime.getRuntime().freeMemory();
data = null;
System.gc();
long m3 = Runtime.getRuntime().freeMemory();
System.out.println("m1: " + m1);
System.out.println("m2: " + m2);
System.out.println("m3: " + m3);
}
}
输出(绝对值在您的环境中会有所不同):
m1: 15887208
m2: 11692888
m3: 15972272
如您所见,此处显式触发垃圾回收会回收与 4 MB 字节数组关联的资源。现在,通常,它既不需要,也不需要 productive/efficient 来显式触发垃圾收集器(而且实际上不能保证这样做会触发收集)。在示例中,这样做是为了说明目的。
垃圾收集 运行 在后台进行,JVM 会按照它认为合适的方式对其进行调度。一种策略是在堆 space(几乎)耗尽时 运行 进行完整收集。事情更复杂,因为不同世代的对象(例如新对象与旧对象)通常存在不同类型的堆。
你能做的最重要的事情就是不要保留对未使用对象的引用。最终,那些未引用的对象将被收集起来,相关的内存将被重新使用。
将文件转换为字节时,不应使用 Files.readAllBytes class。 使用不同的字节转换器后。主要问题是变量中的byte数组无法从内存中删除
示例 1
byte[] x1=new byte[50];
x1=null; //not memory deleting;
示例 2
byte[] x2=null; //memory space:0
x2=new byte[50]; //memory space:50
x2=new byte[100]; //memory space:150
x2=new byte[10]; //memory space:160
x2=null; //memory space:160
我意识到情况就是这样。
我们如何从内存中清除它 space? C语言中有动态内存分配方法(Malloc),java.
中没有删除这块内存 package dragdrop;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.TransferHandler;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class gfgh {
private JFrame frame;
private File_Class file_Class=null;
private JPanel panel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
gfgh window = new gfgh();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public gfgh() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setBackground(Color.BLACK);
frame.getContentPane().add(panel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
memorydelete();
}
});
panel.add(btnNewButton);
this.DragDrop(panel);
}
private void DragDrop(JComponent component)
{
@SuppressWarnings("serial")
TransferHandler transferHandler=new TransferHandler(){
@Override
public boolean canImport(JComponent component,DataFlavor[] dataFlavor)
{
return true;
}
@SuppressWarnings("unchecked")
@Override
public boolean importData(JComponent comp, Transferable t) {
// TODO Auto-generated method stub
List<File> files;
try {
files = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
for(File file:files)
{
System.out.println(file.getAbsolutePath());
System.out.println(file.length());
file_Class=new File_Class();
//file read examle 1 false
// file_Class.file=Files.readAllBytes(Paths.get(file.getAbsolutePath()));
//* file read example 2 false
/*
RandomAccessFile f = new RandomAccessFile(file.getAbsolutePath(), "r");
file_Class.file = new byte[(int)f.length()];
f.readFully( file_Class.file);
*/
//example 3 false
// file_Class.file=readFile(file);
//example 4 false
file_Class.file=readFile(file);
memorydelete();
///////
}
files=null;
Runtime.getRuntime().gc();
} catch (UnsupportedFlavorException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
};
component.setTransferHandler(transferHandler);
}
public void memorydelete()
{
file_Class.file=null;
file_Class=null;
Runtime.getRuntime().gc();
}
public static byte[] readFile(File file) throws IOException {
// Open file
RandomAccessFile f = new RandomAccessFile(file, "r");
try {
// Get and check length
long longlength = f.length();
int length = (int) longlength;
if (length != longlength)
throw new IOException("File size >= 2 GB");
// Read file and return data
byte[] data = new byte[length];
f.readFully(data);
return data;
} finally {
f.close();
}
}
}
class File_Class {
public byte file[];
}
The main problem is that the byte array in the variable cannot be deleted from memory.
没有。这不是问题。
您需要做的就是通过将 null
分配给变量来安排字节数组不可访问...以及任何其他仍保留对数组的引用的可访问变量。
垃圾收集器 (GC) 会处理它。
您不需要致电 System.gc()
。 GC 将在需要 运行 时 运行。如果您尝试干预,您可能只会使您的代码效率低下。
参见:Why is it bad practice to call System.gc()?
真正的问题是以下之一:
文件太大无法读入内存;即大到你得到一个 OOME。如果是这种情况,解决方案是流式传输文件而不是使用
readAllBytes
.您着迷于内存利用率。内存很便宜。程序员的时间是昂贵的。
如果您确实需要 最大限度地减少应用程序的内存使用,那么您使用了错误的编程语言。 Java 不是为这种编程风格设计的。 Java 和 Java 垃圾收集器被设计为在 GC 运行 不频繁并且有足够的空闲内存在收集之间保存垃圾的情况下高效。如果您试图解决这个问题,您的应用程序很可能会浪费大量时间来回收少量内存。
请注意,即使 Java GC 确实(几乎)立即收集了您无法访问的字节数组,它也可能不会 return 回收内存给操作系统。所以你的应用程序的内存占用不会缩小。所以你很可能不会从显式调用 System.gc()
中获得 任何 真正的好处。
如果你确实需要来最小化内存使用量,请使用 C 或 C++
如果你确实需要显式删除对象,请使用 C 或 C++
在Java中,数组是对象。 Java 垃圾收集器最终会处理它们并回收与未引用对象关联的内存。
您可以按如下方式轻松测试:
public class Test {
public static void main(String[] args) {
long m1 = Runtime.getRuntime().freeMemory();
byte[] data = new byte[1024*1024*4];
long m2 = Runtime.getRuntime().freeMemory();
data = null;
System.gc();
long m3 = Runtime.getRuntime().freeMemory();
System.out.println("m1: " + m1);
System.out.println("m2: " + m2);
System.out.println("m3: " + m3);
}
}
输出(绝对值在您的环境中会有所不同):
m1: 15887208
m2: 11692888
m3: 15972272
如您所见,此处显式触发垃圾回收会回收与 4 MB 字节数组关联的资源。现在,通常,它既不需要,也不需要 productive/efficient 来显式触发垃圾收集器(而且实际上不能保证这样做会触发收集)。在示例中,这样做是为了说明目的。
垃圾收集 运行 在后台进行,JVM 会按照它认为合适的方式对其进行调度。一种策略是在堆 space(几乎)耗尽时 运行 进行完整收集。事情更复杂,因为不同世代的对象(例如新对象与旧对象)通常存在不同类型的堆。
你能做的最重要的事情就是不要保留对未使用对象的引用。最终,那些未引用的对象将被收集起来,相关的内存将被重新使用。