Assistive Technology not found: com.sun.java.accessibility.AccessBridge
Rated (5.0 of 5.0) by 2 reviewers.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 settingjavax.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 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
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.