Сборщик мусора зацикливается, когда я использую сокет

Я включаю сокет в свой проект, и он работает хорошо. Мой сервер получил мой запрос, а мое приложение получило ответ. Почти все права, кроме сборщика мусора, начинают зацикливаться и не останавливаются.

Я убил все намерения раньше (включая намерение, которое вызвало сокет), я попробовал socket.disconnect, я закрыл свое приложение (и сборщик мусора все еще работает), но это не сработало.

Сборщик мусора просто останавливается, если я снова запускаю свое приложение или принудительно останавливаю его в настройках.

Где мой код и журнал

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

ОБНОВЛЕНИЕ 4 ФЕВРАЛЯ 2014 Г.

После некоторых тестов я нашел ключ. Метод socket.disconnect вызвал зацикливание в моем приложении, и теперь у меня другая проблема.

Что я должен делать? Если я выполню метод socket.disconnect, GC будет работать бесконечно, и если я не использую socket.disconnect, приложение останется с открытым и работающим сокетом и будет потреблять много батареи.

ОБНОВЛЕНИЕ 6 ФЕВРАЛЯ 2014 Г.

Я до сих пор не решил этот вопрос, но я читал выпуски SocketIO на Github и видел много разработчиков с той же ошибкой, и проблема сохраняется до сегодняшнего дня.

Ссылка на проблемы проекта SocketIO находится здесь: Проблемы Проект SocketIO


person groff07    schedule 29.01.2014    source источник
comment
Ваша проблема не в сборе мусора. Кажется, у вас есть а) утечка и б) из-за этого (или по причине первого) где-то работает поток. Редактировать: Пожалуйста, вставьте правильный код, что-то не так (например, более 1 doInBackground)   -  person zapl    schedule 29.01.2014
comment
@zapl Это правильный код. Я использовал DDMS, как сказал ответ Фаддена, и я подтвердил, что у меня есть поток, но я не знаю, где. Я обновлю свой пост, чтобы дополнить некоторую информацию. Взгляните, пожалуйста. Спасибо   -  person groff07    schedule 29.01.2014
comment
Вы, должно быть, сделали ошибку копирования и вставки. Посмотрите, например, на место }.execute(); где-нибудь внутри метода show(final String idRestaurante).   -  person zapl    schedule 29.01.2014
comment
Я посмотрел классы Socket lib и, возможно, ошибка внутри одного из классов. Я нашел несколько кодов while и синхронизировал. Что вы думаете, @zapl?   -  person groff07    schedule 29.01.2014
comment
Вряд ли. Вы, вероятно, используете его неправильно.   -  person zapl    schedule 29.01.2014
comment
Может быть. Я впервые использую сокет. но я просто использую сокет в этом классе, который я опубликовал.   -  person groff07    schedule 29.01.2014
comment
Я создал глобальный SocketIO. Я подключаюсь и испускаю то, что хочу, в своем конструкторе. И когда я получаю какой-то ответ, я вызываю метод, который создает Intent и вызывает socket.disconnect. Есть что-то еще, что я не сделал?   -  person groff07    schedule 29.01.2014
comment
@zapl... Можешь помочь мне с этим? Я открыл чат, чтобы поговорить. Я не нашел решения. chat.stackoverflow.com/rooms/46704/question-about-socket-and-gc< /а>   -  person groff07    schedule 04.02.2014
comment
@zapl .... Взгляните, пожалуйста, на мой вопрос. У меня есть новая информация.   -  person groff07    schedule 04.02.2014
comment
Спасибо за помощь @zapl. Я попытаюсь найти ошибку, но я думаю, что лучший вариант здесь - создать свой собственный сокет.   -  person groff07    schedule 06.02.2014
comment
Привет, ты уже решил проблему? вы знаете, почему именно сокет не закрывается?   -  person Rijdzuan Sampoerna    schedule 11.02.2014
comment
@oneitusatu Я использовал ответ, который принял здесь. Я искал в Интернете java-websocket-1.3.0.jar, скачал файл и настроил свой файл gradle. Вот и все!   -  person groff07    schedule 11.02.2014


Ответы (3)


У меня была такая же проблема в Android при вызове socket.disconnect().

Вот как это было исправлено.

Проверьте проект socket.io-java-client на странице https://github.com/Gottox/socket.io-java-client;

Скачайте Java-WebSocket-1.3.0.jar;

Замените WebSocket.jar в файле lib проекта socket.io на java-websocket-1.3.0.jar;

Используйте ant для сборки socket.io-java-client в jar;

Затем замените socketio.jar новым, который вы только что создали.

Надеюсь это поможет.

person user3280781    schedule 06.02.2014
comment
К сожалению, у меня уже есть ошибка DEX при создании приложения для Android. Если я попытаюсь получить последнюю версию с github (github.com/TooTallNate/Java-WebSocket) - возможно, будет достаточно построить банку самостоятельно - у меня есть ошибки сборки из-за отсутствия зависимостей (отсутствует класс DefaultSSLWebSocketClientFactory). Я загружаю банку отсюда: search.maven.org/ - person DNax; 21.05.2014
comment
Поскольку jar не работает в моем приложении для Android, мне удалось сделать последнюю версию из TooTallNate. Я просто удалил ссылки на DefaultSSLWebSocketClientFactory из класса WebsocketTransport. - person DNax; 21.05.2014
comment
Привет, он работает с http-сервером. Когда я использую безопасные веб-сокеты, проблема все еще существует. любое исправление? - person Dev; 28.04.2015

Используйте средство отслеживания распределения DDMS, чтобы выяснить, что вызывает выделение, когда он переходит в это состояние. Это позволяет вам видеть трассировку стека для последних 512 сделанных распределений.

Некоторая информация и ссылки находятся в этого сообщения. .

person fadden    schedule 29.01.2014
comment
Я использовал DDMS и подтвердил. После того, как я получу ответ сокета, будет запущен какой-то поток, но я не знаю, где. - person groff07; 29.01.2014
comment
Перейдите к экрану потоков DDMS. Вы должны иметь возможность видеть, какие потоки активно работают (их пользовательское/системное время увеличивается) или есть ли один из них, который быстро запускается и останавливается. Двойной щелчок по потоку даст вам недавнюю трассировку стека. - person fadden; 29.01.2014
comment
Я видел много разных трассировок стека каждый раз, когда нажимал на поток, но я не видел ни одного, указывающего на какую-то строку моих классов @fadden. - person groff07; 29.01.2014

Я сталкиваюсь с той же проблемой с Java webSocket 1.0.3, когда сокет был закрыт, GC бесконечно зацикливался. Я не нашел хорошего решения, чтобы решить эту проблему. Наконец, использовалась альтернативная библиотека nv-websocket-client https://github.com/TakahikoKawasaki/nv-websocket-client.

Что довольно хорошо для реализации веб-сокета на Android и просто в использовании. Больше нет проблем с GC.

person Renaud Boulard    schedule 01.08.2016