Teria como eu criar o sun.misc.BASE64Decoder no java 17?

Preciso usar a classe do seguinte pacote sun.misc.BASE64Decoder em um projeto no java 17,tentei criar a classe por conta própria, porém da o seguinte erro:

The package sun.misc conflicts with a package accessible from another module: jdk.unsupported

Minha classe

package sun.misc;

public class BASE64Decoder {
	   public String decode() {
	        return "meu teste de decodificacao";
	    }
}

Mas pq eu preciso disso?
Preciso manter a compatibilidade entre versões. Não entre versões de java e sim de quem usa minha aplicação.

Nome da classe mudou. Chegou ver esses links?

@edpickler não mudou de nome. São 2 classes diferentes que implementam RFCs diferentes, embora parece não haver mudanças significativas entre elas.

@tiomuri12 vc deveria ter substituído o uso desta classe já no Java 8, mas se vc precisa mesmo, tem um jeito de vc criar a classe sun.misc.BASE64Decoder, eu não recomendo, mas é o seguinte:

Use o sistema de módulos. Para isto basta adicionar um arquivo chamado module-info.java na raiz dos seus pacotes.

O conteúdo deste arquivo poderia ser algo como:

module myappnamehere {
}

Sua estrutura de diretórios ficaria parecida com esta:

├── build.gradle # Ou pom.xml
└── src
    └── main
        └── java
            ├── app
            │   └── Main.java
            ├── module-info.java # 👈🏽 Aqui, fora de qualquer pacote
            └── sun
                └── misc # Copiei do JDK 8, veja abaixo
                    ├── BASE64Decoder.java
                    ├── CEFormatException.java
                    ├── CEStreamExhausted.java
                    └── CharacterDecoder.java

Com isto vc vai ter que declarar explicitamente os módulos que vc deseja usar no seu programa. Por exemplo, se quiser usar Swing, vai ter que adicionar isto ao seu module-info.java:

module myappnamehere {
  requires java.desktop;
}

O que vc pretende fazer criando esta classe? Vc vai usá-la apenas para delegar para a java.util.Base64 ou vc vai tentar usar a implementação original?

Se for usar a implementação original, não sei se vc já viu, mas dá para pegar o código aqui:

https://github.com/openjdk/jdk8u-dev/blob/master/jdk/src/share/classes/sun/misc/BASE64Decoder.java

Mas eu não sei se feriria a licença, então vc tem que pesquisar sobre.

Na minha pesquisa eu achei estas 2 perguntas que podem ser interessantes para vc:

1 curtida

Oi @wldomiciano. Certeza que elas implementam especificações diferentes?

Eu afirmei isso me baseando no que tá na documentação:

jdk8u-dev/BASE64Decoder.java at master · openjdk/jdk8u-dev · GitHub
This class implements a BASE64 Character decoder as specified in RFC1521.


Base64 (Java SE 17 & JDK 17)
This class consists exclusively of static methods for obtaining encoders and decoders for the Base64 encoding scheme. The implementation of this class supports the following types of Base64 as specified in RFC 4648 and RFC 2045.

A 2045 tornou obsoleta a 1521.

Mas eu só quis destacar que não é tão simples quando mudar de nome. O código fonte delas é todinho diferente, com autores diferentes. E também, nas perguntas do StackOverflow que linkei, há relatos de pequenas diferenças no resultado das 2 implementações, apesar de não haver mudanças significativas entre as RFCs.

2 curtidas

@wldomiciano e @edpickler, primeiramente obrigado pela atenção mas minha situação é a seguinte:
Possuo um emissor de relatórios desenvolvido usando as bibliotecas do birt, no java 7, no qual cada relatório possui um layout(um xml), dentro desse layout utilizar scripts java, e em muitos relatórios usamos o sun.misc.BASE64Decoder , para decodar dados que recebemos. Porém fui atualizar a aplicação para o java 17, e acabei caindo nesse impasse, preciso que seja compatível com a versão que estou atualizando e a versão antiga os layouts no caso, por isso que precisava de alguma forma manter esse pacote.
@edpickler estou ciente desse mudança tanto é que quando criei esse classe manualmente implementei essa nova chamada.
@wldomiciano cheguei a implementar esse controle pelo module info, mas tudo que é classe gerou erro de acesso no meu projeto(desculpe, mas nunca trabalhei na pratica com modulos no java talvez estava fazendo algo erro).

Para resolver o problema fiz foi a seguinte:

Criei a classe:

package sun.misc;

import java.util.Base64;

public class BASE64Decoder {
	   public byte[] decodeBuffer(final String inputString) {
		   
	        return Base64.getDecoder().decode(inputString+"IGRlY29kZXI=");//+ decoder
	    }
}

No eclipse para remover o erro do The package sun.misc conflicts with a package accessible from another module: jdk.unsupported fiz a seguinte config:

Quando fiz isso verifiquei que os argumentos usados no eclipse pela jvm eram os seguintes

--limit-modules=java.se,jdk.accessibility,jdk.dynalink,jdk.httpserver,jdk.jartool,jdk.javadoc,jdk.jconsole,jdk.jshell,jdk.jsobject,jdk.management.jfr,jdk.net,jdk.nio.mapmode,jdk.sctp,jdk.security.auth,jdk.security.jgss,jdk.unsupported.desktop,jdk.xml.dom

Ou seja limitando somente para esse modulos, deixando de fora o modulo jdk.unsupported.

Como uso o ant para geração do build, implementei esse argumento, no qual permitiu eu gerar o .war.

Porém ao executar a aplicação no tomcat 9, sem especificar os argumentos que usei no build, deixando somente os argumentos padrão, a aplicação funcionou normalmente, nesse ponto que estou confuso agora, e caso eu especifique os argumentos do build gera erro no modulo java.base
Verifiquei que os argumentos usados pelo tomcat são os seguintes:

--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED

Só pra complementar, pra consultar RFC’s eu prefiro os links que estão em www.rfc-editor.org:

Eu acho mais amigável por estar em HTML, pois tem anchors que linkam direto para cada capítulo ou seção (exemplo), além de ter links para as RFC’s que ela atualizou, etc.

2 curtidas

@wldomiciano então mudou mesmo.
Mas parece que a nova especificação é uma atualização da anterior. Agora sim, entendi e faz sentido.

ps: Não sei se essas informações aqui estão certas:

1 curtida

Nossa, neste cenário eu não tenho nem ideia de como vc poderia fazer.