简体   繁体   中英

java.lang.OutOfMemoryError: Java heap space No more space

I have no clue to why I am getting this error. I cannot find any way to save any more memory. If someone could help me make this more efficient it would be appreciated. Can someone also review my code and see if I did anything silly? Thanks in advance.

MAIN CLASS

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.SpringLayout;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class Main extends JFrame {

    private JPanel contentPane;
    private JTextField Searchq;
    private JScrollPane scrollPane;
    private static JTextArea txtpdisplay;

    /**
     * Launch the application.
     * 
     * @throws IOException
     */

    public static void filelistandfind(String find) throws IOException {
        Files.walk(Paths.get("C:\\Users\\localness\\Desktop\\Locker")).forEach(
                filePath -> {
                    if (Files.isRegularFile(filePath)) {
                        if (filePath.toString().endsWith(".docx")) {
                            try {
                                if (DocxCompair.Readfile(filePath.toString(),
                                        find)) {

                                    //System.out.println(filePath);
                                    txtpdisplay.append(filePath.toString() + "\n");
                                }
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }

                        }
                    }
                });
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Main frame = new Main();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public Main() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 646, 344);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        SpringLayout sl_contentPane = new SpringLayout();
        contentPane.setLayout(sl_contentPane);

        Searchq = new JTextField();
        sl_contentPane.putConstraint(SpringLayout.NORTH, Searchq, 5,
                SpringLayout.NORTH, contentPane);
        sl_contentPane.putConstraint(SpringLayout.WEST, Searchq, 108,
                SpringLayout.WEST, contentPane);
        sl_contentPane.putConstraint(SpringLayout.SOUTH, Searchq, 36,
                SpringLayout.NORTH, contentPane);
        contentPane.add(Searchq);
        Searchq.setColumns(10);

        scrollPane = new JScrollPane();
        sl_contentPane.putConstraint(SpringLayout.NORTH, scrollPane, 3, SpringLayout.SOUTH, Searchq);
        sl_contentPane.putConstraint(SpringLayout.WEST, scrollPane, 5, SpringLayout.WEST, contentPane);
        sl_contentPane.putConstraint(SpringLayout.SOUTH, scrollPane, -9, SpringLayout.SOUTH, contentPane);
        sl_contentPane.putConstraint(SpringLayout.EAST, scrollPane, -5, SpringLayout.EAST, contentPane);
        sl_contentPane.putConstraint(SpringLayout.EAST, Searchq, 0,
                SpringLayout.EAST, scrollPane);
        contentPane.add(scrollPane);

        txtpdisplay = new JTextArea();
        txtpdisplay.setText("");
        scrollPane.setViewportView(txtpdisplay);

        JButton Search = new JButton("Search");
        Search.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent arg0) {
                try {
                    filelistandfind(Searchq.getText());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        sl_contentPane.putConstraint(SpringLayout.NORTH, Search, 2, SpringLayout.NORTH, Searchq);
        sl_contentPane.putConstraint(SpringLayout.WEST, Search, 0, SpringLayout.WEST, scrollPane);
        sl_contentPane.putConstraint(SpringLayout.SOUTH, Search, -3, SpringLayout.SOUTH, Searchq);
        sl_contentPane.putConstraint(SpringLayout.EAST, Search, -6, SpringLayout.WEST, Searchq);
        contentPane.add(Search);
    }
}

DocxCompair Class

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.zip.ZipInputStream;

public final class DocxCompair {
    private static byte[] buffer = new byte[204800];
    private static String result;
    private static int len;

    /*
     * public static void main(String[] args) throws IOException { String s =
     * "Stuart.docx"; String n = "<#tag>"; FileInputStream is = new
     * FileInputStream(s); ZipInputStream zis = new ZipInputStream(is);
     * System.out.println(Readfile(s, n)); }
     */
    private static boolean extractFile(ZipInputStream zipIn, String filePath,
            String text) throws IOException {
        result = "";
        len = 0;
        while ((len = zipIn.read(buffer)) > 0) {
            // System.out.print(new String(buffer));
            System.gc();
            result += result + new String(buffer);
        }
        // System.out.println();
        if (result.contains(text)) {
            return true;
        } else {
            return false;
        }
    }

    private static String texttag;
    private static String fileName;
    private static ZipInputStream zip;

    public static boolean Readfile(String names, String text)
            throws FileNotFoundException {

        // TODO Auto-generated method stub
        fileName = names;
        zip = new ZipInputStream(new FileInputStream(fileName));
        try {
            String name;
            while (true) {
                try {
                    name = zip.getNextEntry().getName();
                    // System.out.println(name);
                    if (name.startsWith("word/document.xml")) {
                        // System.out.println(name);
                        texttag = text;
                        texttag = texttag.replace(">", "&gt;");
                        texttag = texttag.replace("<", "&lt;");
                        // System.out.println(texttag);
                        if (extractFile(zip, name, texttag)) {
                            return true;
                        } else {
                            return false;
                        }

                    }
                } catch (NullPointerException a) {
                    // a.printStackTrace();
                    return false;
                    // break;
                }
            }
            // System.out.println("Done");
        } catch (IOException e) {
            // TODO Auto-generated catch block

            e.printStackTrace();
            return false;
        }
    }
}

Error Message:

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at DocxCompair.extractFile(DocxCompair.java:26)
    at DocxCompair.Readfile(DocxCompair.java:58)
    at Main.lambda$0(Main.java:37)
    at Main$$Lambda$17/772250001.accept(Unknown Source)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
    at java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
    at java.util.Iterator.forEachRemaining(Unknown Source)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source)
    at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)
    at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
    at java.util.stream.ReferencePipeline.forEach(Unknown Source)
    at Main.filelistandfind(Main.java:32)
    at Main$2.mouseClicked(Main.java:106)
    at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)

You are building a giant, giant string. Check out your code:

        result = "";
        len = 0;
        while ((len = zipIn.read(buffer)) > 0) {
            // System.out.print(new String(buffer));
            System.gc();
            result += result + new String(buffer);
        }

let's say I'm reading 2 bytes at a time. Here's what happens with this code.

result = ab // empty + empty + new stuff
result = ababcd // result + result + new stuff.
result = ababcdababcdef // result + result + new stuff
result = ababcdababcdefababcdababcdefgh // result + result + new stuff

Every time you read a chunk of 200k you double the size of your result and then add 200k to it. That means that for a 2mb file (10 reads of 200k) your result is actually just over 204mb.

The reason is because you are doing result += result + new String(buffer); You should be doing result += new String(buffer)

OR, better would be to use a StringBuffer and append to it as you read.

StringBuffer result = new StringBuffer();
len = 0;
while ((len = zipIn.read(buffer)) > 0 ) {
    result.append( new String(buffer));
}

First thing, you don't close all your resources propertly.

Second, there are several things you can try.

First of all, there is a method called Files.find() which you can use. Try this:

private static final BiPredicate<Path, BasicFileAttributes> DOCX_FILES
    = (path, attrs) -> attrs.isRegularFile 
    && path.getFileName().toString().endsWith(".docx");

final Path basePath = Paths.get("C:\\Users\\localness\\Desktop\\Locker");
try (
    final Stream<Path> stream = Files.find(basePath, Integer.MAX_VALUE, DOCX_FILES);
) {
    stream.forEach(path -> whatever)
}

Note that I close the stream here.

Now, it looks like what you want to do is open the docx file as a zip and read the contents of an entry named word/document.xml . Here again, use JSR 203:

final URI uri = URI.create("jar:" + docxPath.toUri());

try (
    final FileSystem zipfs = FileSystems.newFileSystem(uri, Collections.emptyMap());
    final Reader reader = Files.newBufferedReader(zipfs.getPath("word/document.xml"),
        StandardCharsets.UTF_8);
) {
    // use the reader
} catch (FileNotFoundException ignored) {
    // no such file in zip
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM