Java: NoSuchMethodException with reflection when method clearly exists

I've been trying to use Reflection in Java, Here's my code:

String charsetName = "UTF-16LE";
java.nio.charset.CharsetDecoder cd = Charset.forName(charsetName).newDecoder();

Class c = cd.getClass();

Class[] paramTypes = new Class[] {ByteBuffer.class, CharBuffer.class };

try {
     Method method = c.getDeclaredMethod("decodeLoop", paramTypes);
     method.setAccessible(true);
     assertTrue(true);
} catch (NoSuchMethodException | SecurityException e) {
     e.printStackTrace();
     assertTrue(false);
}

Method clearly exists. Java source:

package java.nio.charset;

public abstract class CharsetDecoder {
...
   protected abstract CoderResult decodeLoop(ByteBuffer in,
                                          CharBuffer out);
...
}

The output:

java.lang.NoSuchMethodException:   sun.nio.cs.UTF_16LE$Decoder.decodeLoop(java.nio.ByteBuffer, java.nio.CharBuffer)
at java.lang.Class.getDeclaredMethod(Class.java:2130)
at com.krasutski.AppTest.testDeclaredMethod(AppTest.java:227)
...

if I use a parameter charsetName as

  • "UTF-16LE" - Exception NoSuchMethodException
  • "UTF-16BE" - Exception NoSuchMethodException
  • "UTF-8" - Very good
  • "cp1252" - Very good

How I'm supposed to fix this?

Jon Skeet
people
quotationmark

You're calling getDeclaredMethod on the actual type of cd, whereas it's declared in CharsetDecoder. That can't be the actual type of cd given that it's an abstract class.

Just change this:

Class c = cd.getClass();

to

Class c = CharsetDecoder.class;

The exception goes away at that point. If it's working for UTF-8 and cp1252, that suggests that the classes that are used for that also declare decodeLoop, whereas for UTF-16LE and UTF-16BE they're potentially inherited.

people

See more on this question at Stackoverflow