Categories
discuss

How do I predict when I’m going to run out of memory

We have a swing based application that does complex processing on data. One of the prerequisites for our software is that any given column cannot have too many unique values. If the number is numeric, the user would need to discretize the data before they could from our tool.

Unfortunately, the algorithms we are using are combinatorially expensive in memory depending on the number of unique values per column. Right now with the wrong dataset, the app would run out of memory very quickly. Before doing one of these operations that would run out of memory, we should be able to calculate roughly how much memory the operation will need. It would be nice if we could check how much memory the app currently is using, estimate if the app is going to run out of memory, and show an error message accordingly rather than running out of memory. Using java.lang.Runtime, we can find the free memory, total memory, and max memory, but is this really helpful? Even if it appears we won’t have enough heap space, it could be that if we wait 30 milliseconds the garbage collector will run, and suddenly we have more than enough heap space to run our operation. Is there anyway to really predict if we are going to run out of memory?

Answer

I have done something similar for a database application where the number of rows that were loaded could not be estimated. So in the loop that processes the result set I’m calling a “MemorWatcher” method that would check the memory that was free.

If the available memory goes under a certain threshold the watcher would force a garbage collection and re-check. If there still wasn’t enough memory the watcher method signals this to the caller with an exception. The caller can gracefully recover from that exception – as opposed to the OutOfMemoryException which sometimes leaves Swing totally unstable.

Categories
discuss

“Separators” in ListView

I have an ArrayAdapter which is hooked up to my ListView. I really like the “separators” feature in the Evernote Android application, where they separate items using a datestamp:

screenshot 1 screenshot 2 screenshot 3 enter image description here

I assume what they’re doing is having a view immediately above the list which is set to the value of the current separator, as you can see in the screenshots. (As you scroll past a separator, the text at the top is set to the value of the current separator, ie “January 2011”) How would I actually insert the separators into my ListView?

Answer

A separator is simply a disabled list item, just have your Adapter return the separator where it should be. Seems like SectionIndexer could help.

Categories
discuss

Is there a workaround to the OnItemSelectedListener bug?

I suspect the answer is no, but thought I’d ask…

I have a Spinner that needs to reveal a hidden “proceed” button when the user has made a selection. However, since the OnItemSelectedListener is fired when the spinner is first rendered, and since it doesn’t fire again when the user re-selects the item that is already highlighted, there doesn’t appear to be a way to use this event to reveal a hidden button (or really do anything) contingent on the user having made a selection.

Is there some alternative way to do this?
AdapterView has a ClickListener which just throws an exception, so that’s a non-starter. And it doesn’t seem to have any other notification scheme for when the user first makes contact with it, or when it closes… unless I’m missing something? (wouldn’t be the first time).

All help appreciated.

Answer

I have a Spinner that needs to reveal a hidden “proceed” button when the user has made a selection.

The user has always made a selection. There is no concept of a Spinner without a selection. Hence, do not hide the “proceed” button.

Categories
discuss

Suppressing sign-extension when upcasting or shifting in Java

I have a feeling this is a rather trivial question, but I’m stumped. In my application I’m keying things in a lookup table with a pair of ints. I thought it would be easier to concatenate the two ints into one long and use the single long as a key instead. Coming from a C background, I was hoping something like this would work:

int a, b;
long l = (long)a << 32 | b;

My attempts to replicate this in Java have frustrated me. In particular, because there are no unsigned integral types, I can’t seem to avoid the automatic sign-extension of b (a gets left-shifted so its irrelevant). I’ve tried using b & 0x00000000FFFFFFFF but it surprisingly has no effect. I also tried the rather ugly (long)b << 32 >> 32, but it seemed to be optimized out by the compiler.

I was hoping to do this strictly using bit manipulation with primitives, but I’m starting to wonder if I need to use some sort of buffer object to achieve this.

Answer

I always use my utility class with

public static long compose(int hi, int lo) {
    return (((long) hi << 32) + unsigned(lo));
}
public static long unsigned(int x) {
    return x & 0xFFFFFFFFL;
}

public static int high(long x) {
    return (int) (x>>32);
}
public static int low(long x) {
    return (int) x;
}

For any int x, y (negative or not)

high(compose(x, y)) == x
low(compose(x, y)) == y

holds and for any long z

compose(high(z), low(z)) == z

holds, too.

Categories
discuss

Wifi sleeps, even with Lock

Summary: even when wifi lock is acquired, when the phone is running on batteries, WiFi is disconnected after a while.

I’ve simplified the problem to a single activity with a button that launches a thread. It just sends 100.000 strings to an echo server running on a PC (one string every 100ms). See code below. I can see the traffic with WireShark, and also the echo server shows the strings. Notice how WiFi and power locks are acquired before starting to send (and released after, of course).

However, when the phone is running on battery and the user turns off the phone, it keeps sending strings for some time and then WiFi is disconnected and the phone does not even respond to ping. It takes from 600s to 6000s to be disconnected (the figures are that round, so I think they are important).

It perfectly works when A/C is connected, so I guess it is somehow related to power management.

To test it I just launch the activity, start the echo server, start WireShark, press the “Start” button (android:onClick="doStart"), blocks the phone and let it on the table. I go for lunch or whatever and after 600-6000s I can see the tx errors on WireShark, the echo server has stopped receiving traffic and the phone does not respond to ping.

The phone is 2.2, with WiFi policy set to “sleep after 15m”.

package Odroid.test;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;

import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.View;
import android.widget.Button;

public class Test extends Activity {
  PowerManager _powerManagement = null;
  PowerManager.WakeLock _wakeLock = null;
  WifiManager.WifiLock _wifiLock = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }

  public void doStart(View v) {
    DoerThreadFake t = new DoerThreadFake();
    t.start();
  }

  private class DoerThreadFake extends Thread {
    public void run() {
      runOnUiThread(new Runnable() {
        public void run() {
          ((Button) findViewById(R.id.start)).setText("Doing...");
        }
      });
      _keepOnStart();
      Socket s;
      byte[] buffer = new byte[1000];

      try {
        s = new Socket("192.168.0.16", 2000);
        PrintStream ps = new PrintStream(s.getOutputStream());
        InputStream is = s.getInputStream();
        for (int i = 0; i < 100000; i++) {
          ps.println(System.currentTimeMillis() +"("+(new Date()).toString() +") : " + i);
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          while (is.available() > 0) {
            int a = is.available();
            if (a > 1000) a = 1000;
            is.read(buffer, 0, a); // Clean echo
          }
        }
      } catch (UnknownHostException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      _keepOnStop();
      runOnUiThread(new Runnable() {
        public void run() {
          ((Button) findViewById(R.id.start)).setText("Done");
        }
      });
    }

    private void _keepOnStart() {
      if (_powerManagement == null) {
        _powerManagement = (PowerManager) getSystemService(Context.POWER_SERVICE);
      }
      if (_wakeLock == null) {
        _wakeLock = _powerManagement.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE,
            "0 Backup power lock");
      }
      _wakeLock.acquire();
      WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
      if (wifiManager != null) {
        _wifiLock = wifiManager.createWifiLock("0 Backup wifi lock");
        _wifiLock.acquire();
      }
    }

    private void _keepOnStop() {
      if ((_wifiLock != null) && (_wifiLock.isHeld())) {
        _wifiLock.release();
      }
      if ((_wakeLock != null) && (_wakeLock.isHeld())) {
        _wakeLock.release();
      }
    }
  }
}

The manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="Odroid.test"
  android:versionCode="1"
  android:versionName="1.0"
>
  <uses-sdk android:minSdkVersion="4" />

  <application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
  >
    <activity
      android:name=".Test"
      android:label="@string/app_name"
    >
      <intent-filter>
        <action
          android:name="android.intent.action.MAIN" />
        <category
          android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

  </application>
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />

</manifest>

Any idea?

Answer

There are numerous bugs on the Android bug tracker to do with wifi sleep/power saving mode and even apps available that attempt to rectify this. So it is quite likely that you are not doing anything wrong.

http://code.google.com/p/android/issues/detail?id=9781
http://code.google.com/p/android/issues/detail?id=1698

Also check out wififixer which is an open source project which may help you with code to keep the connection alive

http://wififixer.wordpress.com/

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..