如何清除物体形成伊甸园空间JAVA8?

时间:2016-06-22 14:37:27

标签: java memory-leaks jvm

我希望内存稳定,不受“垃圾收集器”的干扰,也不会超出内存使用量。

package com.company;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.net.URI;

public class Main {

    public static void main(String[] args) {

        new GetThread().start();
    }

    static class GetThread extends Thread {

        private HttpGet httpGet = new HttpGet();
        private final CloseableHttpClient httpClient;

        public GetThread() {

            this.httpClient = HttpClientBuilder.create()
                    .build();

            try{
                httpGet.setURI(new URI("https://play.google.com/store/apps/details?id=com.whatsapp"));
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }

        @Override
        public void run()
        {
            StringBuilder body;

            for (int i = 0; i < 50000; i++)
            {
                try{
                    CloseableHttpResponse response = httpClient.execute(httpGet);

                    body  = new StringBuilder(EntityUtils.toString(response.getEntity()));

                    EntityUtils.consume(response.getEntity());
                    response.close();

                    body.setLength(0);

                    response = null;
                    body = null;
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }

        }


    }
}

有问题的一行

body = EntityUtils.toString(response.getEntity());

我尝试将此对象设置为null,但它仍然存在于Eden空间中。

Yourkit graphs

Memory dump

虽然对象为null,但它仍然存在于内存中,直到“垃圾收集器”清除内存。

谢谢!

3 个答案:

答案 0 :(得分:0)

您无法从Eden中删除对象,只有GC可以执行此操作。 设置对null的引用不会清除对象占用的空间。

答案 1 :(得分:0)

避免垃圾收集和增加(堆)内存使用的唯一方法是不在堆上分配新对象。

在Java中,当分配内存,使用一段时间然后不再引用时,垃圾收集器是恢复内存并使其可用于重用的机制。如果您创建对象然后停止引用它们,它们将继续使用堆的那部分,直到垃圾收集器运行。

这就是Java的工作方式。

答案 2 :(得分:0)

解决方案,在对象中重用&不要创建字符串对象

package com.company;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;

public class Main {

    public static void main(String[] args) {

        new GetThread().start();
    }

    static class GetThread extends Thread {

        private HttpGet httpGet = new HttpGet();

        private final CloseableHttpClient httpClient;
        private CloseableHttpResponse response;

        private StringBuilder content = new StringBuilder();
        private char[] buffer = new char[1024];


        public GetThread() {

            this.httpClient = HttpClientBuilder.create()
                    .build();

            try{
                httpGet.setURI(new URI("https://play.google.com/store/apps/details?id=com.whatsapp"));
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }

        @Override
        public void run()
        {
            Reader in;
            int rsz;

            for (int i = 0; i < 50000; i++)
            {
                content.setLength(0);

                try{
                    response = httpClient.execute(httpGet);

                    InputStream is = response.getEntity().getContent();

                    in = new InputStreamReader(is, "UTF-8");

                    for (;;)
                    {
                        rsz = in.read(buffer, 0, buffer.length);

                        if (rsz < 0)
                            break;

                        content.append(buffer, 0, rsz);
                    }

                    in.close();

                    EntityUtils.consume(response.getEntity());
                    response.close();
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }
}

这个代码比第一个代码好得多,分析结果 Mmeory graphs

enter image description here