Tecnología de asistencia no encontrada: com.sun.java.accessibility.AccessBridge


Me encontré pintado en un pequeño rincón de desarrollo recientemente. Nuestro software tiene un poquito de código Java Swing (un JOptionPane con un JPasswordField en él), y recibimos un par de informes de fallas de una configuración incompleta de Java Assistive Technology. La esencia del informe de bloqueo:

java.awt.AWTError: Assistive Technology not found: com.sun.java.accessibility.AccessBridge
 at java.awt.Toolkit.loadAssistiveTechnologies(Toolkit.java:773)
 at java.awt.Toolkit.getDefaultToolkit(Toolkit.java:872)
 at javax.swing.UIManager.<clinit>(UIManager.java:357)
 at javax.swing.text.JTextComponent.updateUI(JTextComponent.java:332)
 at javax.swing.JPasswordField.updateUI(JPasswordField.java:148)
 at javax.swing.text.JTextComponent.<init>(JTextComponent.java:306)
 at javax.swing.JTextField.<init>(JTextField.java:212)
 at javax.swing.JPasswordField.<init>(JPasswordField.java:121)
 at javax.swing.JPasswordField.<init>(JPasswordField.java:68)

¡Soy 100% para apoyar dispositivos de asistencia, pero en este caso los clientes que informaron el bloqueo no usan dispositivos de asistencia! Un poco de investigación con esos dos clientes, y determinamos que algún otro software con el que han estado en contacto instaló un JRE diferente y activó la configuración de Tecnología de Asistencia . No rastreamos el software, pero ambos clientes eran estudiantes universitarios, por lo que suponemos que puede ser algún software proporcionado por sus escuelas.

Dado que solo tenemos un pequeño componente Swing en el software, los clientes no estaban usando ningún dispositivo de asistencia, y no es sencillo deshabilitar / desinstalar / configurar el puente de acceso de Java para una instalación de Java que no conocemos (porque se instaló para otro software) , decidimos hacer la pregunta (con suerte) más simple: ¿podemos anular la configuración del puente de acceso para desactivarla solo para nosotros?

Probamos algunos métodos diferentes:

  • Configurando nuestro propio .accessibility.properties in our installed JRE folder. This doesn't work because the .accessibility.properties in the user's home folder takes precedence over the JRE folder.
  • Limpiando la propiedad javax.accessibility.assistive_technologies y escenario javax.accessibility.screen_magnifier_present a falso al comienzo del programa.
  • Anulando las propiedades usando banderas de línea de comando.

La única solución que funcionó para nosotros fue anular las propiedades con indicadores de línea de comando cuando lanzamos nuestro software. Estas son las banderas que necesita:

-Djavax.accessibility.assistive_technologies 
-Djavax.accessibility.screen_magnifier_present=false

Es de esperar que alguien encuentre útil esta información. Una vez más, esta no es una solución para que los dispositivos de asistencia y Java Access Bridge funcionen para su software (¡sería una buena idea!), Pero podría ser útil si uno de sus usuarios tiene alguna falla de configuración de JRE antigua o conflictiva en su computadora. esta excepción en su software, y para que las cosas funcionen nuevamente, solo tiene que desactivar el puente de acceso.

Note: You could also ask your customer to look for a .accessibility.properties file in their home folder (%userprofile% on Windows) and delete it, but overriding the contents of this file using the command line flags above requires no back-and-forth with the customer or potential customer.

Update diciembre 31, 2018:

This solution worked for us through Java 8, but when we upgraded to Java 11, the -Djavax.accessibility.assistive_technologies flag triggers a crash because it incorrectly specifyies that we want to load an AccessibilityProvider with empty string as a name, instead of an empty list of providers. The change in the parsing happened in this changeset in Java 9. I filed a bug report, but I also needed a new workaround.

Since there is now no way to specify "load no classes", to override the accessibility settings to NOT load com.sun.java.accessibility.AccessBridge we need to load a class of our own. Here's my simple implementation of a no-op AccessibilityProvider:

import javax.accessibility.AccessibilityProvider;

public class EmptyAccessibilityProvider extends javax.accessibility.AccessibilityProvider {
    public String getName() {
        return "EmptyAccessibilityProvider";
    }

    public void activate() {}
}

I add this class to my classes, and then adjust my command line flags to load EmptyAccessibilityProvider (add a package as makes sense for your source code):

-Djavax.accessibility.assistive_technologies=EmptyAccessibilityProvider
-Djavax.accessibility.screen_magnifier_present=false

Just for reference, here's the new crash on Java 9, 10, and 11 if you specify the empty list to -Djavax.accessibility.assistive_technologies

java.awt.AWTError: Assistive Technology not found:
at java.desktop/java.awt.Toolkit.newAWTError(Toolkit.java:472)
at java.desktop/java.awt.Toolkit.fallbackToLoadClassForAT(Toolkit.java:488)
atjava.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
atjava.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
atjava.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1603)
atjava.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
atjava.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
atjava.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
atjava.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
atjava.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
atjava.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
atjava.desktop/java.awt.Toolkit.loadAssistiveTechnologies(Toolkit.java:532)
at java.desktop/java.awt.Toolkit.getDefaultToolkit(Toolkit.java:613)
at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:198)
at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:217)
at Main.getProgJIcon(Main.java:881)
at EncryptionReader.createWaitDialog(EncryptionReader.java:793)
at EncryptionReader.getKeybagFromFile(EncryptionReader.java:389)
at EncryptionReader.getKeybagFromFile(EncryptionReader.java:282)
at ManifestDBLocked.readEncryptedManifestDB(ManifestDBLocked.java:20)
at MBDB.readBackupManifest(MBDB.java:168)
at MBDB.readBackupManifest(MBDB.java:102)
at ScavengerFileFilter.openBackupDID(ScavengerFileFilter.java:182)
at ScavengerUI$15.run(ScavengerUI.java:967)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassNotFoundException:
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at java.desktop/java.awt.Toolkit.fallbackToLoadClassForAT(Toolkit.java:485)
... 23 more

java.lang.ClassNotFoundException:
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at java.desktop/java.awt.Toolkit.fallbackToLoadClassForAT(Toolkit.java:485)
atjava.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
atjava.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
atjava.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1603)
atjava.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
atjava.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
atjava.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
atjava.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
atjava.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
atjava.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
atjava.desktop/java.awt.Toolkit.loadAssistiveTechnologies(Toolkit.java:532)
at java.desktop/java.awt.Toolkit.getDefaultToolkit(Toolkit.java:613)
at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:198)
at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:217)
at Main.getProgJIcon(Main.java:881)
at EncryptionReader.createWaitDialog(EncryptionReader.java:793)
at EncryptionReader.getKeybagFromFile(EncryptionReader.java:389)
at EncryptionReader.getKeybagFromFile(EncryptionReader.java:282)
at ManifestDBLocked.readEncryptedManifestDB(ManifestDBLocked.java:20)
at MBDB.readBackupManifest(MBDB.java:168)
at MBDB.readBackupManifest(MBDB.java:102)
at ScavengerFileFilter.openBackupDID(ScavengerFileFilter.java:182)
at ScavengerUI$15.run(ScavengerUI.java:967)
at java.base/java.lang.Thread.run(Thread.java:834)

1 Comments



Ivan Nikitin

Ivan Nikitin septiembre 9, 2018

Thank you for the post. Saved a lot of time for me!