线程“Thread-9”中的异常java.lang.OutOfMemoryError:Java堆空间

时间:2015-10-25 14:35:53

标签: java heap

我一直在为我的游戏写一个更新程序。

  1. 它检查下拉框中的.version文件,并将其与本地.version文件进行比较。

  2. 如果文件的本地版本中缺少任何链接,则会逐个下载所需的链接。

  3. 这是它显示的错误

    Exception in thread "Thread-9" java.lang.OutOfMemoryError: Java heap space
    at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:209)
    at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:204)
    at com.fox.listeners.ButtonListener.UpdateStart(ButtonListener.java:132)
    at com.fox.listeners.ButtonListener$1.run(ButtonListener.java:58)
    

    它仅显示某些计算机,而不是所有计算机,这是readFile方法

    private byte[] readFile(URL u) throws IOException {
        return readFile(u, getFileSize(u));
    }
    
    private static byte[] readFile(URL u, int size) throws IOException {
        byte[] data = new byte[size];
        int index = 0, read = 0;
        try {
            HttpURLConnection conn = null;
            conn = (HttpURLConnection) u.openConnection();
            conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
            InputStream is = conn.getInputStream();
            progress_a = 0;
            progress_b = data.length;
            while(index < data.length) {
                read = is.read(data, index, size-index);
                index += read;
                progress_a = index;
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    
        return data;
    }
    
    private byte[] readFile(File f) {
        byte[] data = null;
        try {
            data = new byte[(int)f.length()];
    
            @SuppressWarnings("resource")
            DataInputStream dis = new DataInputStream(new FileInputStream(f));
            dis.readFully(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
    

    这是运行的主要方法

    public void UpdateStart() {
        System.out.println("Starting Updater..");
    
        if(new File(cache_dir).exists() == false) {
            System.out.print("Creating cache dir.. ");
            while(new File(cache_dir).mkdir() == false);
            System.out.println("Done");
        }
    
    
        try {
            version_live = new Version(new URL(version_file_live));
        } catch(MalformedURLException e) {
            e.printStackTrace();
        }
    
        version_local = new Version(new File(version_file_local));
    
        Version updates = version_live.differences(version_local);
    
        System.out.println("Updated");
    
        int i = 1;
        try {
            byte[] b = null, data = null;
            FileOutputStream fos = null;
            BufferedWriter bw = null;
    
    
            for(String s : updates.files) {
                if(s.equals(""))
                    continue;
    
    
                System.out.println("Reading file "+s);
                AppFrame.pbar.setString("Downloading file "+ i + " of "+updates.files.size());
                if(progress_b > 0) {
                    s = s + " " +(progress_a * 1000L / progress_b / 10.0)+"%";
                }
    
                b = readFile(new URL(s));
    
    
    
                progress_a = 0;
                progress_b = b.length;
    
                AppFrame.pbar.setString("Unzipping file "+ i++ +" of "+updates.files.size());
    
                ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(b));
                File f = null, parent = null;
                ZipEntry entry = null;
                int read = 0, entry_read = 0;
                long entry_size = 0;
                progress_b = 0;
    
                while((entry = zipStream.getNextEntry()) != null)
                    progress_b += entry.getSize();
    
                zipStream = new ZipInputStream(new ByteArrayInputStream(b));
    
                while((entry = zipStream.getNextEntry()) != null) {
                    f = new File(cache_dir+entry.getName());
                    if(entry.isDirectory())
                        continue;
    
                    System.out.println("Making file "+f.toString());
    
                    parent = f.getParentFile();
                    if(parent != null && !parent.exists()) {
                        System.out.println("Trying to create directory "+parent.getAbsolutePath());
                        while(parent.mkdirs() == false);
                    }
    
                    entry_read = 0;
                    entry_size = entry.getSize();
                    data = new byte[1024];
                    fos = new FileOutputStream(f);
    
                    while(entry_read < entry_size) {
                        read = zipStream.read(data, 0, (int)Math.min(1024, entry_size-entry_read));
                        entry_read += read;
                        progress_a += read;
                        fos.write(data, 0, read);
                    }
                    fos.close();
                }
    
                bw = new BufferedWriter(new FileWriter(new File(version_file_local), true));
                bw.write(s);
                bw.newLine();
                bw.close();
            }
        } catch(Exception e) {
            e.printStackTrace();
            return;
        }
    
        System.out.println(version_live);
        System.out.println(version_local);
        System.out.println(updates);
        CacheUpdated = true;
        if(CacheUpdated) {
            AppFrame.pbar.setString("All Files are downloaded click Launch to play!");
        }
    
    }
    

    我不明白为什么它适用于我的一些玩家,然后我的其他一些玩家并不是我一整天都试图解决这个问题而且我在这一点上非常难过但这似乎是我唯一需要解决的大问题。

2 个答案:

答案 0 :(得分:0)

要么增加分配给JVM的内存(How can I increase the JVM memory?),要么确保内存中加载的文件不是很大(如果是,你需要找到备用解决方案,或者只是一次读取它的块而不是将整个内容加载到内存中。)

答案 1 :(得分:0)

分几个步骤进行更新。这里有一些Java 8的伪代码。它比你写的要简短,因为Java有很多内置的工具,你重写的效率要低得多。

// Download
Path zipDestination = Paths.get(...);
try (InputStream  in = source.openStream()) {
  Files.copy(in, zipDestination);
}

// Unzip
try (ZipFile zipFile = new ZipFile(zipDestination.toFile())) {
  for (ZipEntry e: Collections.list(zipFile.entries())) {
    Path entryDestination = Paths.get(...);
    Files.copy(zipFile.getInputStream(e), entryDestination);
  }
}

// Done.