-2

I'm moving a project to Java11

I already changed sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl with java.lang.reflect.ParameterizedType (as specified here), now is the turn of MalformedByteSequenceException:

warning: MalformedByteSequenceException is internal proprietary API and may be removed in a future release import com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException;

it's being use in a snippet of code that create objects from XML files. More precisely in a try-catch.

    try {
        ...
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(stream);

        NodeList list = document.getChildNodes();

        fillProcessStack(document);
        ...
        list = list.item(0).getChildNodes();
        createItems(list, parent);

    } catch (MalformedByteSequenceException e) {
        //"Any char in your xml file has a wrong format: " + e.getLocalizedMessage()
    } catch (SAXParseException sax) {
        ...
    } catch (Exception e) {
        ...
    }

Anyway I cant find anything online regarding this.

The closest I can think of is UnsupportedEncodingException, but I'm not sure.

Also, it's possible this is a relict of some old code copied from the net, and apparently if I remove it everything looks still fine for the compiler.

So, is there any general/good recommendations about it regarding Java11?

Edit: for the guy seeking to close this question because

Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Reproducible Example.

I'll try to be explain clearer.

There is no debugging help here, in Java11 some packages are not exported to public, like sun.* and they shouldnt be used normally (unless specific conditions). Code works fine under jdk8, but under ojdk11 it complains, so I could either use some workarounds to make them visible anyway at runtime or make it right and get rid of them. The latter is what I'm trying to do. Given I couldn't find anything online, I'm asking here.

elect
  • 6,765
  • 10
  • 53
  • 119
  • What do you mean "being used"? You mean some of your code does new() and throw for that exception type? – GhostCat Jul 26 '19 at 10:51
  • If you remove it from what? – user207421 Jul 26 '19 at 10:51
  • Are you *catching* this exception at the moment specifically, or explicitly *throwing* it from your code? If you're throwing it, you can presumably throw whatever you like in its place (including a custom exception if you so wish?) – Michael Berry Jul 26 '19 at 10:52
  • In a `try-catch`, I modified the question. It's closed source, I'll try to show a shallow copy of that – elect Jul 26 '19 at 10:54
  • 1
    20 seconds with `javap` told me that it extends `java.io.CharConversionException`. I can't really see much reason to catch anything beyond the `IOException` and `SAXException` that are documented for `DocumentBuilder.parse()`. – user207421 Jul 26 '19 at 10:56
  • @user207421 ok, fine, then I'm leaning toward removal. You can answer and if nothing else comes up, I'll take that – elect Jul 26 '19 at 11:07
  • 'And then?' What does that mean? Tell us how you've going to treat `CharConversionException` or even `IOException` differently from any other exception and we'll talk. Otherwise there is no question to answer. NB 'they shouldnt be used normally (unless specific conditions)': no; they shoudln't be used at all, period. – user207421 Jul 26 '19 at 11:09
  • @user207421 'and then' was referred to the previous version of your previous comment. There are some cases, such as accessing raw pointers in the most efficient way, where for example `sun.unsafe` is the most performant way. – elect Jul 26 '19 at 11:12
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197044/discussion-between-elect-and-user207421). – elect Jul 26 '19 at 11:23
  • 1
    It seems, the behavior of the parser changed anyway. Starting with JDK 11, it doesn’t throw a `MalformedByteSequenceException`, but a `SAXParseException` whose cause is a `MalformedByteSequenceException`. So attempts to catch `MalformedByteSequenceException` will have no effect anyway. – Holger Jul 26 '19 at 11:53
  • @Holger, if you want to answer that, I'll take it – elect Jul 26 '19 at 12:18

1 Answers1

5

MalformedByteSequenceException extends CharConversionException, which extends IOException, which the parse method forces you to catch anyway. So when catching IOException or CharConversionException, you’ll also catch MalformedByteSequenceException if thrown directly.

However there seems to be a behavioral change of the XML parser in JDK 11. When I try, e.g.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(new byte[] { 1, 2, 3, -5 }));

I get

Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Invalid byte 1 of 1-byte UTF-8 sequence.
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:262)
        at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
        at java.xml/javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122)
        at TestXmlParser.main(TestXmlParser.java:14)
Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:702)
        at java.xml/com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:568)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1904)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:1770)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:1808)
        at java.xml/com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:158)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:860)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:246)
        ... 3 more

instead of the

Exception in thread "main" com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
        at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
        at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:554)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1742)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(XMLEntityScanner.java:1619)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(XMLEntityScanner.java:1657)
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:193)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:232)
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)
        at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)
        at TestXmlParser.main(TestXmlParser.java:14)

of previous versions.

In other words, parse now throws a SAXParseException with a cause initialized to a MalformedByteSequenceException. So, to detect that the problem is a malformed byte sequence, resp. text in the wrong encoding, you’d need something like

catch(SAXException ex) {
    if(ex.getCause() instanceof CharConversionException) {
        System.out.println("maformed bytes or wrong encoding: "+ex.getMessage());
    }
}

To handle newer and older versions, you’d need something like

catch(CharConversionException ex) {
    System.out.println("malformed bytes or wrong encoding: "+ex.getMessage());
}
catch(SAXException ex) {
    if(ex.getCause() instanceof CharConversionException) {
        System.out.println("malformed bytes or wrong encoding: "+ex.getMessage());
    }
}

resp.

catch(CharConversionException ex) {
    handle(ex);
}
catch(SAXException ex) {
    if(ex.getCause() instanceof CharConversionException) {
        handle((CharConversionException)ex.getCause());
    }
}

…

static void handle(CharConversionException ex) {
    // just an example
    System.out.println("malformed bytes or wrong encoding: "+ex.getMessage());
}
Holger
  • 285,553
  • 42
  • 434
  • 765