【问题标题】:Garbage Collector looping when I use socket当我使用套接字时垃圾收集器循环
【发布时间】:2014-01-29 14:19:30
【问题描述】:

我在我的项目中加入了一个套接字,它运行良好。 我的服务器收到了我的请求,我的应用收到了答案。 除了垃圾收集器之外,几乎所有权利都开始循环并且没有停止。

我之前杀死了所有的意图(包括调用套接字的意图),我尝试了 socket.disconnect,我关闭了我的应用程序(并且 GC 仍在运行)但没有工作。

如果我再次运行我的应用程序或在配置中强制停止,GC 就会停止。

我的代码和日志在哪里

public class ListaRestaurantesActivity extends Activity implements NumberPicker.OnValueChangeListener {

    private static Context context;
    private static Dialog dialog;
    private static NumberPicker numberPickerDialog;
    private Button botaoOkDialog;
    private Button botaoCancelDialog;
    private ListView lv_telaListaRestaurante_Lista;
    private ListaRestaurantesAdapter lra;
    private List<ListaRestauranteTO> listaRestauranteTO;

    public static void entraMesaAprovado(String idRestaurante) {
        Intent mesa = new Intent(context, SelectedRestauranteActivity.class);
        mesa.putExtra("numeroMesa", String.valueOf(numberPickerDialog.getValue()));
        mesa.putExtra("idRestaurante", idRestaurante);
        context.startActivity(mesa);
        dialog.dismiss();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lista_restaurante);

        lv_telaListaRestaurante_Lista = (ListView) findViewById(R.id.lv_telaListaRestaurante_Lista);

        dialog = new Dialog(ListaRestaurantesActivity.this);
        dialog.setContentView(R.layout.view_alert_dialog);
        dialog.setTitle(R.string.txt_alertDialog_Cabecalho);

        numberPickerDialog = (NumberPicker) dialog.findViewById(R.id.np_viewAlertDialog_NumeroMesa);
        botaoOkDialog = (Button) dialog.findViewById(R.id.bt_viewAlertDialog_OK);
        botaoCancelDialog = (Button) dialog.findViewById(R.id.bt_viewAlertDialog_Cancel);

        new AsyncTask<Context, Void, Void>() {
            private UtilWS ws;
            private JsonElement jsonElement;
            private Gson gson = new Gson();
            private Type type = new TypeToken<ListaRestauranteTO>() { }.getType();

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                ws = new UtilWS();
                listaRestauranteTO = new ArrayList<ListaRestauranteTO>();
            }

            @Override
            protected Void doInBackground(Context... params) {
                context = params[0];
                String[] postResult = ws.post(UtilWS.URL_LISTA_LOCAIS, "");
                if (postResult[0].equals("200")) {
                    JsonObject temp = new JsonParser().parse(postResult[1]).getAsJsonObject();
                    JsonArray jsonArray = temp.getAsJsonArray("restaurantes");
                    for (int i = 0; i < jsonArray.size(); i++) {
                        jsonElement = jsonArray.get(i);
                        listaRestauranteTO.add((ListaRestauranteTO) gson.fromJson(jsonElement, type));
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                lra = new ListaRestaurantesAdapter(context, listaRestauranteTO);
                lv_telaListaRestaurante_Lista.setAdapter(lra);
            }
        }.execute(this);

        lv_telaListaRestaurante_Lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
                Log.i("Contents", " = " + view.getTag());
                show((String) view.getTag());
            }
        });
    }

    public void show(final String idRestaurante)
    {
        String[] listaMesas = null;

        for (int i = 0; i < listaRestauranteTO.size(); i++) {
            for (int j = 0; j < listaRestauranteTO.get(i).getMesas().size(); j++) {
                if (listaRestauranteTO.get(i).getMesas().get(j).getRestaurante_id().equals(idRestaurante)) {
                    if (listaMesas == null) {
                        listaMesas = new String[listaRestauranteTO.get(i).getMesas().size()];
                    }
                    listaMesas[j] = listaRestauranteTO.get(i).getMesas().get(j).getNumero();
                } else {
                    j = listaRestauranteTO.get(i).getMesas().size() + 1;
                }
            }
        }
        numberPickerDialog.setMinValue(1);
        numberPickerDialog.setMaxValue(listaMesas.length);
        numberPickerDialog.setDisplayedValues(listaMesas);
        numberPickerDialog.setWrapSelectorWheel(false);
        numberPickerDialog.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
        numberPickerDialog.setOnValueChangedListener(this);
        botaoOkDialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... params) {
                        new ReceiveCallback(context, String.valueOf(numberPickerDialog.getValue()), idRestaurante);
                        return null;
                    }
                }.execute();
            }
        });
        botaoCancelDialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });
        dialog.show();
    }

    @Override
    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
    }
}

class ReceiveCallback implements IOCallback {
    private SocketIO socket = new SocketIO();
    private FBSessionsManager fbSessionsManager;
    private Context context;
    private String idRestaurante;

    public ReceiveCallback(Context context, String mesaNumero, String idRestaurente) {
        this.context = context;
        idRestaurante = idRestaurente;
        fbSessionsManager = new FBSessionsManager(this.context);
        try {
            socket.connect("http://192.168.25.5:3001/", this);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            socket.emit("solicita-mesa", new JSONObject().put("userId", fbSessionsManager.getStoredPrivateSession()[1])
                    .put("mesaNumero", mesaNumero).put("restauranteId", idRestaurente));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(JSONObject json, IOAcknowledge ack) {
        try {
            Log.i("Server said:" + json.toString(2), ".");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(String data, IOAcknowledge ack) {
        Log.i("Server said: " + data, ".");
    }

    @Override
    public void onError(SocketIOException socketIOException) {
        Log.i("an Error occured", ".");
        socketIOException.printStackTrace();
    }

    @Override
    public void onDisconnect() {
        Log.i("Connection terminated.", ".");
    }

    @Override
    public void onConnect() {
        Log.i("Connection established", ".");
        Intent i = new Intent(context, MensagemAguardeActivity.class);
        context.startActivity(i);
    }

    @Override
    public void on(String event, IOAcknowledge ack, Object... args) {
        JSONObject object = (JSONObject) args[0];
        if (event.equals("confirmacao")) {
            try {
                if ((Boolean) object.get("confirmado")) {
                    ListaRestaurantesActivity.entraMesaAprovado(idRestaurante);
                }
                socket.disconnect();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        if (event.equals("remove-prato")) {
        }
    }
}

01-29 12:02:10.161    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 6589K, 30% free 16328K/23076K, paused 1ms+2ms, total 31ms
01-29 12:02:16.341    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 18334K, 60% free 12654K/31144K, paused 1ms+1ms, total 53ms
01-29 12:02:22.471    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14657K, 60% free 12646K/31144K, paused 1ms+11ms, total 64ms
01-29 12:02:28.591    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14648K, 54% free 12651K/27460K, paused 1ms+1ms, total 52ms
01-29 12:02:34.731    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14654K, 54% free 12649K/27464K, paused 11ms+0ms, total 63ms
01-29 12:02:40.841    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14654K, 54% free 12646K/27464K, paused 1ms+1ms, total 53ms
01-29 12:02:46.991    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14650K, 54% free 12652K/27464K, paused 1ms+1ms, total 52ms
01-29 12:02:53.091    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14658K, 54% free 12654K/27468K, paused 1ms+1ms, total 52ms
01-29 12:02:59.221    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14658K, 54% free 12642K/27468K, paused 1ms+1ms, total 47ms
01-29 12:03:05.591    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14646K, 54% free 12641K/27468K, paused 12ms+1ms, total 66ms
01-29 12:03:11.781    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14646K, 54% free 12649K/27456K, paused 12ms+13ms, total 75ms
01-29 12:03:17.951    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14654K, 54% free 12648K/27464K, paused 1ms+11ms, total 63ms
01-29 12:03:24.071    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14654K, 54% free 12644K/27464K, paused 11ms+1ms, total 64ms
01-29 12:03:30.191    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14650K, 54% free 12654K/27460K, paused 1ms+1ms, total 52ms
01-29 12:03:36.331    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14658K, 54% free 12648K/27468K, paused 12ms+11ms, total 74ms
01-29 12:03:42.471    8994-8996/br.com.timo.xxxx D/dalvikvm﹕ GC_CONCURRENT freed 14650K, 54% free 12642K/27468K, paused 11ms+0ms, total 63ms

我需要做什么来停止这个 GC 循环?它消耗大量电池。

感谢和问候。

更新

我正在使用这个套接字库。

SocketIO Lib

2014 年 2 月 4 日更新

经过一番测试,我找到了线索。 socket.disconnect 方法导致了我的应用程序中的循环,现在我遇到了另一个问题。

我该怎么办?如果我执行 socket.disconnect 方法,GC 将无限运行,如果我不使用 socket.disconnect,应用程序将保持套接字打开并正常工作,并且会消耗大量电池。

2014 年 2 月 6 日更新

我仍然没有解决这个问题,但是我在 Github 上阅读了 SocketIO 的问题,我看到很多开发人员遇到同样的错误,直到今天问题仍然存在。

SocketIO项目issues的链接在这里:Issues Project SocketIO

【问题讨论】:

  • 你的问题不是垃圾回收。似乎您有 a)泄漏和 b)由于(或前者的原因)某处正在运行的线程。编辑:请粘贴正确的代码,有问题(例如超过 1 个doInBackground
  • @zapl 这是正确的代码。我像fadden的回答一样使用了DDMS,我确认我有一个线程正在运行,但我不知道在哪里。我将更新我的帖子以补充一些信息。请看一看。谢谢
  • 您一定是复制粘贴错误。例如,查看show(final String idRestaurante) 方法中某处的}.execute(); 的位置。
  • 我查看了 Socket lib 的类,可能是其中一个类中的错误。我找到了一些while代码并同步。你怎么看@zapl?
  • 不太可能。你可能用错了。

标签: java android sockets garbage-collection socket.io


【解决方案1】:

在调用 socket.disconnect() 时,我在 Android 中遇到了同样的问题。

这是如何修复的。

https://github.com/Gottox/socket.io-java-client签出socket.io-java-client项目;

下载Java-WebSocket-1.3.0.jar;

将socket.io项目的l​​ib文件中的WebSocket.jar替换为java-websocket-1.3.0.jar;

使用ant构建socket.io-java-client到jar;

然后将 socketio.jar 替换为你刚刚构建的新的。

希望这会有所帮助。

【讨论】:

  • 遗憾的是,我在构建 android 应用程序时已经添加了 DEX 错误。如果我尝试从 github (github.com/TooTallNate/Java-WebSocket) 获取最新的 - 也许我自己构建 jar 就足够了 - 由于缺少依赖项(缺少 DefaultSSLWebSocketClientFactory 类),我有构建错误。我下载的jar来自这里:search.maven.org/…
  • 由于 jar 无法在我的 android 应用程序上运行,我设法从 TooTallNate 制作了最新版本。我刚刚从 WebsocketTransport 类中删除了对 DefaultSSLWebSocketClientFactory 的引用。
  • 嗨,它与http服务器一起工作。当我使用安全网络套接字时,问题仍然存在。有什么办法吗?
【解决方案2】:

使用 DDMS 分配跟踪器找出导致分配进入此状态的原因。它可以让您查看最近 512 次分配的堆栈跟踪。

一些信息和链接在this post

【讨论】:

  • 我使用了 de DDMS 并确认了。收到socket的应答后,有一些线程在运行,但我不知道在哪里。
  • 转到 DDMS 线程屏幕。您应该能够看到哪些线程正在积极运行(它们的用户/系统时间增加),或者是否有一个快速启动和停止。双击一个线程可以获得最近的堆栈跟踪。
  • 每次单击线程时,我都会看到很多不同的堆栈跟踪,但我没有看到一个指向我的类@fadden 的某行。
【解决方案3】:

当套接字关闭时,我在 Java webSocket 1.0.3 中遇到了同样的问题,GC 无限循环。我没有找到任何好的解决方案来解决这个问题。最后使用了一个替代库 nv-websocket-client https://github.com/TakahikoKawasaki/nv-websocket-client.

在Android上实现web socket非常好,而且使用简单。没有更多的 GC 问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2013-05-25
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多