Thread Safety

Posted on 2018-04-27 17:18 in Blog • Tagged with concurency, java

While digging through the code to get answer to a question needed to proceed with a story authoring activity, I stumbled upon the following code. Most of the the class is omitted and the names of the routine/ structure simplified.

...

public void insertIntoMap(long key, Object value) {
    synchronized (readWriteLock) {
        this.map.put(key, value);
    }
}

...

public Map getMap() {
    synchronized (readWriteLock) {
        return this.map;
    }
}

...

The part that drew my attention was the getMap() method. Wait to acquire the lock, then return a reference to the object. The call of the method, when it access the object, is no longer protected by the readWriteLock. Therefore, we have the makings of a ConcurrentAccessException on our hands. There are two primary ways to resolve this issue.

Follow the copy on access pattern

public Map getMap() {
    synchronized (readWriteLock) {
        return this.map.clone();
    }
}

Eliminate the need for the read/ write lock

private static final ConcurrentHashMap<> map = new ConcurrentHashMap<Long, Object>();

...

public void insertIntoMap(long key, Object value) {
    this.map.put(key, value);
}

...

public Map getMap() {
    return this.map;
}

I'm a fan of the second approach. Using a data structure that has built in thread-safety reduces the likelihood the developer will forget to use a lock somewhere and introduce a concurrency problem.


Continue reading

Embedding Libraries in Java Executables (JAR)

Posted on 2010-04-18 15:43 in Blog • Tagged with java, programming

I’ve been working on developing a small Java utility for use at my place of work. The utility is used for parsing log files and extracting useful engineering data. Often, this work is performed out in the field literally in the middle of a desert] and most of the time the laptop they are using is handed to them as they are walking out the door to the test range. For this reason, the utility we’ve created has been designed to be as stand-alone as possible, requiring no install.

One of the most requested features is the ability to graph the change of a variable over time. The students on my team identified an open source graphing library that worked perfectly. The problem was we now had to ship two files to the test range, not much, but twice as many as before.

Solution

Using Netbeans we were able to modify the build process to embed the library inside the resulting Jar file. Place the following code in your build.xml file, modifying only the red text to match the name of the final Jar.

<target name="package-for-store" depends="jar">

<!—

http://java.sun.com/developer/technicalArticles/java\_warehouse/single\_jar/

Change the value of this property to be the name of your JAR, minus the .jar extension. It should not have spaces.

<property name="store.jar.name" value="MyJarName"/>

-->

<property name="store.jar.name" value="Bundled_JAR"/>

<!-- don't edit below this line -->

<property name="store.dir" value="store"/>

<property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>

<echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>

<delete dir="${store.dir}"/>

<mkdir dir="${store.dir}"/>

<jar destfile="${store.dir}/temp\_final.jar" filesetmanifest="skip">

<zipgroupfileset dir="dist" includes="\*.jar"/>

<zipgroupfileset dir="dist/lib" includes="\*.jar"/>

<manifest>

<attribute name="Main-Class" value="${main.class}"/>

</manifest>

</jar>

<zip destfile="${store.jar}">

<zipfileset src="${store.dir}/temp\_final.jar" excludes="META-INF/\*.SF, META-INF/\*.DSA, META-INF/\*.RSA"/>

</zip>

<delete file="${store.dir}/temp\_final.jar"/>

</target>

What’s happening behind the scenes?

Netbeans performs the following actions to build the final Jar. (Which you can do with a script if you feel so inclined.)

  1. Compile all source files to class files
  2. Extract all class files from library Jar files
  3. Compress all class files (include library files) into new single Jar file

Continue reading

Problems with Java'’s parseInt

Posted on 2010-04-01 21:41 in Blog • Tagged with java, programming

Background

I work in an industry that generates a lot of binary encode data. Primarily from the lab at my office, but occasionally we get data that was collected at a government test range. In order to understand the data, it goes through a process called, “Data Reduction”, which converts the binary/ hex encoded data (test data) into simple decimal numbers (engineering data) that can get used by excel. The data fields vary in size, from a byte up to a long, and it is usually unsigned data. A tool was written last spring (2009) with the help of a regional university to automate the data conversion process and it is currently being extended (2010).

Problem

The students discovered that negative numbers were not being parsed correctly. Sometimes giving an invalid value (byte: 0x80), other times they caused a NumberFormatException (int: 0xFFFFFFFF). I told them I would look into the problem. It quickly became apparent what the problem was; Integer.parseInt doesn’t under two’s complement values.

parseInt takes a hex encoded string and returns an int. In the case of negative numbers, parseInt looks for a negative sign at the beginning of the string. It does not examine the hex code within the string. When a negative byte or short was parsed, the method treated it as a positive int, and parsed accordingly. When a negative int was provided, the method threw an exception.

Cause of the Exception

The Java int has “two” fields: 31 bits of data, and 1 bit of sign. When a negative hex string was provided, parseInt saw 32 bits of data, determined it was an overflow condition, and threw the exception.

Solution

With the root cause of the problem in hand, I was quickly able to write a solution. I first wrote a routine that determined if the proved string was negative, based on its type (or size). If it was negative, I replace the original data string with its two’s complement and added a negative sign to the front. Now, parseInt returns the expected results.

Code

/** Test if string is negative  
 *  
 * @param number - hex string containing data  
 * @param bytes - number of bytes in data type (8 bit vs 16 bit, etc)  
 *  
 * @ return True means the number is negative  
 */  
public static boolean isNumberNegative(String number, int bytes){  
    if((number.length() / 2) < bytes ){ // check if top bit even has a value in it  
        return false;  
    }

    // extract first two characters into number  
    int bit = Integer.parseInt( number.substring(0,2), 16);  
    bit >>= 7; // down shift seven bits

    return (bit == 1); // top bit set == negative  
}

/**  
 * Make the hex string negative by performing two's complement  
 * @param hex the string to make negative  
 * @return input string after 2's complement reversal  
 */  
public static String makeNegativeInt(String hex){  
    String finalString = "";  
    int[] list = new int[ hex.length() / 2 ];

    // copy hex string into array  
    for(int i = 0; i < hex.length() / 2; i++){  
        list[i] = Integer.parseInt( hex.substring(i*2, i*2 +2), 16);  
    }

    // make each block negative  
    int add = 1;  
    int topBitOld = 0;  
    int topBitNew = 0;

    for(int i = list.length -1 ; i &gt;= 0; i--){  
        list[i] ^= 0xFF; // flip bits  
        topBitOld = (list[i] >> 7) & 1;             // save old top bit  
        list[i] += add;                             // possibly add bit  
        topBitNew = (list[i] >> 7) & 1;             // save new top bit  
        if((topBitOld == 1) && (topBitNew == 0)){   // check if overflow occurred  
            add = 1;  
        } else {  
            add = 0;  
        }  
        list[i] &= 0xFF;  
    }

    // rebuild hex string  
    for(int i = 0; i &lt; list.length; i++){  
        finalString += padHex(list[i], 2);  
    }

    return finalString;  
}

/**  
 * This pads a number with zeros, after it has been converted to  
 * hexidecimal format, sans 0x.  
 *  
 * @param number Number to be converted to hexidecimal  
 * @param length Final length of padded string  
 * @return String after padding  
 */  
public static String padHex(int number, int length){  
    char padding = '0';  
    String s = Integer.toHexString(number);  
    while(s.length() < length){  
        s = padding + s;  
    }  
    return s;  
}  

Continue reading