Assistive Technology not found: com.sun.java.accessibility.AccessBridge

   Rated (5.0 of 5.0) by 2 reviewers.
Kelly Heffner Wilkerson

Categories: Development | View Comments

I found myself painted into a little development corner recently. Our software has a very tiny bit of Java Swing code in it (one JOptionPane with a JPasswordField in it), and we received a couple of crash reports from an incomplete Java Assistive Technology setup. The gist of the crash report:

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)

I am 100% for supporting assistive devices, but in this case the customers reporting the crash don't use any assistive devices! A little sleuthing with those two customers, and we determined that some other software they have been in contact with installed a different JRE and turned on the Assistive Technology settings. We didn't track down the software, but both customers were university students, so we assume it may be some software provided by their schools.

Given that we only have one small Swing component in the software, the customers weren't actually using any assistive devices, and it is not straightforward to disable/uninstall/configure the Java access bridge for a Java install that is unknown to us (because it was installed for different software), we decided to ask the (hopefully) simpler question: can we override the access bridge setting to turn it off just for us?

We tried a few different methods:

  • Setting up our own .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.
  • Clearing the property javax.accessibility.assistive_technologies and setting javax.accessibility.screen_magnifier_present to false at the start of the program.
  • Overriding the properties using command line flags.

The only solution that worked for us was overriding the properties with command line flags when we launch our software. Here are the flags you need:

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

Hopefully someone finds this information helpful. Again, this is not a solution to get assistive devices and Java Access Bridge working for your software (which would be a good thing!) but it might be helpful if one of your users has some old or conflicting JRE setup cruft on their computer triggering this exception in your software, and to get things working again, you just need to turn the access bridge off.

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 December 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 specifies 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 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 java.base/java.lang.Thread.run(Thread.java:834)

Further update November 1, 2019:

According to the bug report the issue is fixed as of JDK 13 b21 and the spec was updated to support empty string. I have not transitioned to JDK 13 yet to verify yet. For JDK 9 through 13b21, you will still need the workaround described above.