首页 > 解决方案 > 如何从内存中删除变量?

问题描述

将文件转换为字节时,不应使用 Files.readAllBytes 类。使用不同的字节转换器后。主要问题是变量中的字节数组无法从内存中删除。

示例 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

我意识到情况就是这样。

我们如何从内存空间中清除它?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[];
}

标签: javaarraysjava-memory-model

解决方案


主要问题是变量中的字节数组无法从内存中删除。

不,这不是问题。

您需要做的就是通过分配null给变量 ... 和任何其他仍保留对数组的引用的可访问变量来安排字节数组不可访问。

垃圾收集器 (GC) 会处理它。

你不需要打电话System.gc()。GC 将在需要运行时运行。如果你尝试干预,你可能只会让你的代码效率低下。

请参阅:为什么调用 System.gc() 是不好的做法?


真正的问题是以下之一:

  1. 文件太大,无法读入内存;即大到你得到一个OOME。如果是这种情况,解决方案是流式传输文件而不是使用readAllBytes.

  2. 您正在沉迷于内存利用率。内存很便宜。程序员的时间很昂贵。

如果您确实需要最小化应用程序的内存使用量,那么您使用的编程语言是错误的。Java 不是为这种编程风格而设计的。Java 和 Java 垃圾收集器被设计为在 GC 不经常运行并且有足够的空闲内存在收集之间保存垃圾的情况下高效。如果您试图与之抗争,您的应用程序很可能会浪费大量时间来回收少量内存。

请注意,即使 Java GC 确实(几乎)立即收集了您无法访问的字节数组,它也可能不会将回收的内存返回给操作系统。所以你的应用程序的内存占用不会缩小。因此,您很可能不会从显式调用中获得任何System.gc()真正的好处。

如果您确实需要最小化内存使用量,请使用 C 或 C++

如果您确实需要显式删除对象,请使用 C 或 C++


推荐阅读