private static Unwrapper getSpecificUnwrapper(Class<?> type) {
        // See if we're already determined this
        if (unwrapperCache.containsKey(type)) {
            // We will never remove from the cache, so this ought to be thread safe
            return unwrapperCache.get(type);
        }
        
        try {
            final Method find = type.getMethod("getHandle");
            
            // It's thread safe, as getMethod should return the same handle 
            Unwrapper methodUnwrapper = new Unwrapper() {
                @Override
                public Object unwrapItem(Object wrappedObject) {
                    
                    try {
                        return find.invoke(wrappedObject);
                        
                    } catch (IllegalArgumentException e) {
                        throw new RuntimeException("Illegal argument.", e);
                    } catch (IllegalAccessException e) {
                        // Should not occur either
                        return null;
                    } catch (InvocationTargetException e) {
                        // This is really bad
                        throw new RuntimeException("Minecraft error.", e);
                    }
                }
            };
            
            unwrapperCache.put(type, methodUnwrapper);
            return methodUnwrapper;
            
        } catch (SecurityException e) {
            throw new RuntimeException("Security limitation for " + type.getName(), e);
            
        } catch (NoSuchMethodException e) {
            // Try getting the field unwrapper too
            Unwrapper fieldUnwrapper = getFieldUnwrapper(type);
            
            if (fieldUnwrapper != null)
                return fieldUnwrapper;
            else
                throw new RuntimeException("Cannot find method getHande() in " + type.getName(), e);
        }
    }