private DecoderBase new_decoder (int size, long max, SessionBase session, int version) {
        
        if (options.decoder == null) {
            if (version == V1Protocol.VERSION)
                return new V1Decoder (size, max, session);
            return new Decoder (size, max);
        }
        
        try {
            Constructor<? extends DecoderBase> dcon;
            
            if (version == 0)  {
                dcon = options.decoder.getConstructor (int.class, long.class);
                return dcon.newInstance (size, max);
            } else {
                dcon = options.decoder.getConstructor (int.class, long.class, IMsgSink.class, int.class);
                return dcon.newInstance (size, max, session, version);
            }
        } catch (SecurityException e) {
            throw new ZError.InstantiationException (e);
        } catch (NoSuchMethodException e) {
            throw new ZError.InstantiationException (e);
        } catch (InvocationTargetException e) {
            throw new ZError.InstantiationException (e);
        } catch (IllegalAccessException e) {
            throw new ZError.InstantiationException (e);
        } catch (InstantiationException e) {
            throw new ZError.InstantiationException (e);
        }
    }