pyjnius icon indicating copy to clipboard operation
pyjnius copied to clipboard

Static fields synchronization bug?

Open eulerreich opened this issue 10 years ago • 0 comments

I'm using the android library from SymmetricDS through pyjnius. Specifically, there's a registry class containing a private static hashmap. I've modified it to log program states, as follows:

/**
 * Licensed to JumpMind Inc under one or more contributor
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU General Public License, version 3.0 (GPLv3)
 * (the "License"); you may not use this file except in compliance
 * with the License.
 *
 * You should have received a copy of the GNU General Public License,
 * version 3.0 (GPLv3) along with this library; if not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jumpmind.symmetric.android;

import java.util.HashMap;
import java.util.Map;

import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class SQLiteOpenHelperRegistry {

    static private Map<String, SQLiteOpenHelper> sqliteOpenHelpers = new HashMap<String, SQLiteOpenHelper>();
    static private final String TAG = "SQLITE_OPEN_HELPER_REGISTRY";

    public static void register(String name, SQLiteOpenHelper helper) {
        Log.i(TAG, "registering " + name + " with " + helper.toString());
        sqliteOpenHelpers.put(name, helper);
        Log.i(TAG, "hashmap size is " + sqliteOpenHelpers.size());
        Log.i(TAG, "hashmap is " + sqliteOpenHelpers.toString());
        Log.i(TAG, "hashmap keys are " + sqliteOpenHelpers.keySet().toString());
    }

    public static SQLiteOpenHelper lookup(String name) {
        Log.i(TAG, "looking up " + name);
        Log.i(TAG, "is " + name + " a key? " +
                (sqliteOpenHelpers.containsKey(name) ? "yes" : "no"));
        Log.i(TAG, "hashmap is " + sqliteOpenHelpers.toString());
        Log.i(TAG, "hashmap keys are " + sqliteOpenHelpers.keySet().toString());
        return sqliteOpenHelpers.get(name);
    }

}

Using autoclass to reflect this to the Python side seems to instantiate a different SQLiteOpenHelperRegistry class that's specific to the Python side, and is distinct from the one on the Java side. In particular, calling lookup and register from the Python side will show that the hashmap is as expected, i.e. if I register a new key-value pair it the hashmap's toString() will show correspondingly. But when calling lookup and register from the Java side will show that the hashmap is empty!

The java calls are caught in the middle of 2 python calls, so the log results are something like

hashmap is {helperkey=HelperInstance}
...
hashmap is {}
...
hashmap is {helperkey=HelperInstance}

where the middle log is from the Java side calls to lookup and the other ones are form the Python side.

The Java side is a Service started by the Python side through a call to startService from an autoclassed PythonActivity. Not sure if that has to do with it. The Android documentation specified that services stay in the same thread unless configured otherwise, so there shouldn't be multithread synchronization bugs.

Either way this is an undesired behavior. The hashmap should be the same whether accessed from the Java or the Python side.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

eulerreich avatar Dec 14 '13 05:12 eulerreich