New smart class FastCharset

Ulf Zibis Ulf.Zibis at gmx.de
Sat Aug 1 15:20:34 UTC 2009


Martin, Sherman, Dalibor,

I'm proud to present a new patch, which could dramatically improve the 
memory-footprint and instantiation performance of charsets usage, so 
Charset instances could directly be hold in cache.
The footprint of the code is again little smaller than before.

Provided patch fixes:
6862158 Make sun.nio.cs.* charset objects light-weight
6850361 Avoid 2-step lookup in sun.nio.cs charset providers
6790402 Speed-up FastCharsetProvider
6795536 No system start for file.encoding=x-SJIS_0213
6792535 NoClassDefFoundError after failed new StreamEncoder(out, lock, 
Charset.defaultCh
6850337 Hasher.java interprets given option value badly
6853677 Provide names of supported charsets -> now superfluous

Do you like to review and/or sponsor my CR ?

See:
https://bugs.openjdk.java.net/show_bug.cgi?id=100098

As the code of the new FastCharset is so tiny and flexible, I paste it 
here directly...
Using it's De/Encoders in general would make interfaces ArrayDecoder ad 
ArrayEncoder superfluous.
For charsets with huge mappings it is foreseen to split class Mapping 
for decoders and encoders.

Thanks,

Ulf



package sun.nio.cs;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.UnsupportedCharsetException;

class FastCharset extends Charset implements HistoricallyNamedCharset {

    private final String pkgName;
    final String mappingClsName; // package private for 
ExternalCharsetProvider
    private transient Decoder decoder;
    private transient Encoder encoder;

    FastCharset(String className, String canonicalName, String... aliases) {
        super(canonicalName, aliases);
        pkgName = getClass().getPackage().getName();
        mappingClsName = className;
    }
    FastCharset(String packageName, String className, String 
canonicalName, String[] aliases) {
        super(canonicalName, aliases);
        pkgName = packageName;
        mappingClsName = className;
    }

    public String historicalName() {
        return mapping().historicalName;
    }

    public boolean contains(Charset cs) {
        return cs.name().equals(name()) ||
                mapping().isASCII && cs.name().equals("US-ASCII");
    }

    public Decoder newDecoder() {
        return decoder().clone();
    }

    public Encoder newEncoder() {
        if (encoder == null)
            encoder = decoder().newEncoder();
        return encoder.clone();
    }

    private final Decoder decoder() {
        if (decoder == null)
            decoder = mapping().newDecoder(this);
        return decoder;
    }

    final Mapping mapping() {
        try {
            return ((Class<Mapping>) Class.forName(
                pkgName+'.'+mappingClsName)).newInstance();
        } catch (ClassNotFoundException ex) {
            throw new NoClassDefFoundError(ex.getMessage());
        } catch (ReflectiveOperationException ex) {
            Error error = new InternalError("Can't instantiate class 
["+pkgName+'.'+mappingClsName+"]");
            error.initCause(ex);
            throw error;
        }
    }


    static abstract class Decoder<M extends Mapping>
            extends CharsetDecoder implements Cloneable, ArrayDecoder {

        M mapping;

        Decoder(FastCharset cs, M mapping,
                float averageCharsPerByte, float maxCharsPerByte) {
            super(cs, 1.0f, 1.0f);
            this.mapping = mapping;
        }

        protected Decoder<M> clone() {
            try {
                return (Decoder<M>)super.clone();
            } catch (CloneNotSupportedException ex) {
                return null;
            }
        }

        Encoder<M> newEncoder() {
            return mapping.newEncoder(this);
        }
    }


    static abstract class Encoder<M extends Mapping>
            extends CharsetEncoder implements Cloneable, ArrayEncoder {

        M mapping;

        Encoder(Decoder<M> decoder,
                   float averageBytesPerChar, float maxBytesPerChar) {
            super(decoder.charset(), 1.0f, 1.0f);
            mapping = decoder.mapping;
            mapping.initEncoderMaps();
        }

        protected Encoder<M> clone() {
            try {
                return (Encoder<M>)super.clone();
            } catch (CloneNotSupportedException ex) {
                return null;
            }
        }
    }
}





More information about the core-libs-dev mailing list