JDK-8068866 : NPE while implementing Hash Table
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,8u25
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: os_x
  • CPU: x86
  • Submitted: 2015-01-09
  • Updated: 2015-01-15
  • Resolved: 2015-01-15
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
OS X 10.10.1 (14B25)

A DESCRIPTION OF THE PROBLEM :
Implementing a Hash Table for self-education purposes. 

Trying to use technique described here: http://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java

Introduced bug in my class, crashed the compiler

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
try to compile provided class using javac

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
code compiles or produces error
ACTUAL -
javac crashes

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.NullPointerException
	at com.sun.tools.javac.comp.DeferredAttr$DeferredChecker.quicklyResolveMethod(DeferredAttr.java:1333)
	at com.sun.tools.javac.comp.DeferredAttr$DeferredChecker.visitApply(DeferredAttr.java:1223)
	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
	at com.sun.tools.javac.tree.TreeScanner.scan(TreeScanner.java:49)
	at com.sun.tools.javac.comp.DeferredAttr$FilterScanner.scan(DeferredAttr.java:901)
	at com.sun.tools.javac.comp.DeferredAttr.isDeferred(DeferredAttr.java:1088)
	at com.sun.tools.javac.comp.Attr.attribArgs(Attr.java:701)
	at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1834)
	at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
	at com.sun.tools.javac.comp.Attr.visitTypeCast(Attr.java:3125)
	at com.sun.tools.javac.tree.JCTree$JCTypeCast.accept(JCTree.java:1814)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
	at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:649)
	at com.sun.tools.javac.comp.Attr.visitVarDef(Attr.java:1093)
	at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:852)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
	at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:692)
	at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:1142)
	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
	at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:1035)
	at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
	at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
	at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
	at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:4342)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4252)
	at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4181)
	at com.sun.tools.javac.comp.Attr.attrib(Attr.java:4156)
	at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1248)
	at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
	at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
	at com.sun.tools.javac.main.Main.compile(Main.java:523)
	at com.sun.tools.javac.main.Main.compile(Main.java:381)
	at com.sun.tools.javac.main.Main.compile(Main.java:370)
	at com.sun.tools.javac.main.Main.compile(Main.java:361)
	at com.sun.tools.javac.Main.compile(Main.java:56)
	at com.sun.tools.javac.Main.main(Main.java:42)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.HashSet;
import java.util.Set;

public class ArrayHashTable<K,V> implements Map<K,V> {

	private K[] keys;
	private V[] values;

	public ArrayHashTable(int size){
		initArrays( size );
	}

	private void initArrays( int size){
		final K[] k = (K[]) Array.newInstance( K.class.getName(), size );
		final V[] v = (V[]) Array.newInstance( V.class.getName(), size );
		
		keys = k;
		values = v;
	}

	public void clear(){
		//initArrays( keys.getClass(), , keys.length );
	}
	
	public boolean containsKey( Object key ){ 
		for( int i = 0; i < keys.length; ++i ){
			if( key.equals( keys[i] ) ){
				return true;
			}
		}
		return false;
	}
	
	public boolean containsValue( Object value ){ 
		for( int i = 0; i < values.length; ++i ){
			if( value.equals( values[i] ) ){
				return true;
			}
		}
		return false;
	}
	
	public Set<Map.Entry<K,V>> entrySet() { 
		Set<Map.Entry<K,V>> result = new HashSet<Map.Entry<K,V>>();
		return result;
	}
	
	public boolean equals( Object o ) { 
		if( ! (o instanceof ArrayHashTable) ){
			return false;
		} else {
			ArrayHashTable aht = (ArrayHashTable) o;
			if( keys.length != aht.keys.length ) return false;
			if( values.length != aht.values.length ) return false;
			
			for( int i = 0; i < keys.length; i++ ){
				if( ! keys[i].equals( aht.keys[i] ) ) return false;
				if( ! values[i].equals( aht.values[i] ) ) return false;
			}
			
			return true;
		}
	} 
	
	public V get( Object key ) { 
		int keyIndex = -1;
		for( int i = 0; i < keys.length; ++i ){
			if( keys[i].equals( key ) ){
				keyIndex = i;
			}
		}
		if( keyIndex == -1 ) return null;
		return values[keyIndex];
	}
	
	public int hashCode() { 
		return 0;
	}
	
	public boolean isEmpty() { 
		return keys.length == 0;
	}
	
	public Set<K> keySet() { 
		Set<K> result = new HashSet<K>();
		for( int i = 0; i < keys.length; ++i ){
			result.add( keys[i] );
		}
		return result;
	}
	
	public V put( K key, V value ) { return null; }
	
	public void putAll(Map<? extends K,? extends V> m) {}
	
	public V remove( Object key ) { return null; }
	
	public int size() { return 0; }
	
	public Collection<V> values() { return null; }
	
	
	// unit test main function
	public static void main( String[] args ){
		ArrayHashTable<String,String> aht = new ArrayHashTable<String, String>( 1000 );
		
		System.out.println( aht.entrySet() );
	}
}
---------- END SOURCE ----------


Comments
Checked this with JDK 8 and 8u25 and could reproduce the issue.
13-01-2015