Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8029606

IllegalArgumentException when use custom Charset to encode String

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 7u45
    • core-libs

      FULL PRODUCT VERSION :
      java version "1.7.0_45"
      Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
      Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      $ uname -a
      Linux ayanichkin-desktop 3.11.0-14-generic #21-Ubuntu SMP Tue Nov 12 17:04:55 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      I need custom 1-byte charset, that actually stored in database. But when I attempt encode some text with it, I received IllegalArgumentException (some inputs processed correctly always, some only sometimes).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Use attached source code of 1-byte table charset. Output copied from http://www.compileonline.com/compile_java_online.php, but on my machine this also fails.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Encoded byte array with my charset.
      ACTUAL -
      # Compiling the source code....
      $javac Table1ByteCharset.java 2>&1

      # Executing the program....
      $java -Xmx128M -Xms16M Table1ByteCharset
      Exception in thread "main" java.lang.IllegalArgumentException
      at java.nio.Buffer.position(Buffer.java:236)
      at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:600)
      at java.lang.StringCoding.encode(StringCoding.java:370)
      at java.lang.String.getBytes(String.java:939)
      at Table1ByteCharset.main(Table1ByteCharset.java:56)

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      import java.util.Arrays;
      import java.nio.ByteBuffer;
      import java.nio.CharBuffer;
      import java.nio.charset.Charset;
      import java.nio.charset.CharsetEncoder;
      import java.nio.charset.CharsetDecoder;
      import java.nio.charset.CoderResult;

      public class Table1ByteCharset extends Charset {
          // Encode each char with its position in table, [0; 255].
          final char[] table = new char[255];
          class Encoder extends CharsetEncoder {
              Encoder() {
                  super(Table1ByteCharset.this, 1.0f, 1.0f, new byte[]{(byte)'?'});
              }
              @Override
              protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
                  while (in.remaining() > 0) {
                      if (out.remaining() == 0) {
                          return CoderResult.OVERFLOW;
                      }
                      final int b = indexOf(in.get());
                      if (b < 0) {
                          return CoderResult.unmappableForLength(1);
                      }
                      out.put((byte)b);
                  }
                  return CoderResult.UNDERFLOW;
              }
          }
          class Decoder extends CharsetDecoder {
              Decoder() {
                  super(Table1ByteCharset.this, 1.0f, 1.0f);
              }
              @Override
              protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
                  while (in.remaining() > 0) {
                      if (out.remaining() == 0) {
                          return CoderResult.OVERFLOW;
                      }
                      out.put(table[ index(in.get()) ]);
                  }
                  return CoderResult.UNDERFLOW;
              }
              private int index(byte b) {return b < 0 ? 256 + (int)b : (int)b;}
          }
          Table1ByteCharset() {super("Table1ByteCharset", null);}
          @Override
          public boolean contains(Charset cs) {return this == cs;}
          
          @Override
          public Encoder newEncoder() {return new Encoder();}
          @Override
          public Decoder newDecoder() {return new Decoder();}

          public static void main(String[] args) {
              System.out.println(Arrays.toString("Hello World".getBytes(new Table1ByteCharset())));
          }
          int indexOf(char ch) {
              for (int i = 0; i < table.length; ++i)
                  if (table[i]==ch) return i;
              return -1;
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      In my case I just not use Charset subclass.

            sherman Xueming Shen
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: