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