添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account MacOS, Linux (Issue does NOT occur on Windows)

Architecture:
x86_64 (AdoptOpenJDK 11.0.4. Also occurs on Oracle Java 8).

Description
Java's PrintService.lookupPrintServices() does not return newly added (and thus still returns newly removed) printers in a timely fashion unless the Java application is restarted.

Steps

  • Run the following code:
    import javax.print.PrintService;
    import javax.print.PrintServiceLookup;
    public class ListingDelay {
        public static void main(String[] args) {
            new Thread(() -> {
                try {
                    while(true) {
                        PrintService[] printers = PrintServiceLookup.lookupPrintServices(null, null);
                        System.out.println("Found " + printers.length + " printers.  (Sleeping for 5 seconds)");
                        Thread.sleep(5000);
                } catch (Exception e) {
                    e.printStackTrace();
            }).run();
    
  • Add or remove a printer. The number will not change for 1-2 minutes.
  • Restart the program. Now the number will change.
  • this works correctly or Ubuntu's 11.0.4

    @karianna can you share some details with your unit tests? They do not match mine.

    I've tested the above code using Ubuntu 18.04 and the openjdk version from Canonical and the issue exists there for me as well.

    /usr/lib/jvm/java-11-openjdk-amd64/bin/java -version
    openjdk version "11.0.4" 2019-07-16
    OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
    OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
    

    I installed a local Zebra printer and the CUPS-PDF virtual printer:

    Start up the code snippet.

  • Java correctly reports 2 printers.
  • Adding an additional printer, java incorrectly reports 2 printers (should be 3)
  • Start up the code snippet.

  • Java correctly reports 3 printers.
  • Removing a printer, java incorrectly reports 3 printers (should be 2)
  • this works correctly or Ubuntu's 11.0.4

    @karianna can you share some details with your unit tests? They do not match mine.

    I've tested the above code using Ubuntu 18.04 and the openjdk version from Canonical and the issue exists there for me as well.

    /usr/lib/jvm/java-11-openjdk-amd64/bin/java -version
    openjdk version "11.0.4" 2019-07-16
    OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
    OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
    

    I installed a local Zebra printer and the CUPS-PDF virtual printer:

    Start up the code snippet.

  • Java correctly reports 2 printers.
  • Adding an additional printer, java incorrectly reports 2 printers (should be 3)
  • Start up the code snippet.

  • Java correctly reports 3 printers.
  • Removing a printer, java incorrectly reports 3 printers (should be 2)
  • I'm using 18.04.3 (LTS) and canonical's 11.0.4

    openjdk 11.0.4 2019-07-16
    OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
    OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, sharing)
    

    I run your test above and when adding and removing the CUPS-PDF virtual printer it adds and takes away the number as expected. With Adopt 11.0.4, it does not.

    One can only assume we're referencing a different version of a native library.

    Machine updated. I can confirm that openjdk11 from Ubuntu refreshes the printer list although it takes 1-2 minutes to do so.

    I also have the same results on Adopt, 1-2 minutes the printer listing updates. Can you confirm that waiting up to 2 minutes, it finally updates?

    Printer listings do not refresh on CUPS Printer listings take a long time to refresh on CUPS Aug 13, 2019

    Thanks for the investigation and updates! I'll run mine again...

    When I add a printer it picks that up in 10-15 seconds, removing took about 1-2 minutes. I suspect this is falling within 30-60 second caching / timing windows with the O/S.

    Aha - try adding -Dsun.java2d.print.polling=false to the java command line before executing your program.

    e.g. java -Dsun.java2d.print.polling=false ListingDelay

    That seems to add and remove the printers roughly at the speed of them being added/removed from the O/S config.

    @karianna that works very well.

    Specifically:

    System.setProperty("sun.java2d.print.polling", "false");

    This adds about 90ms of lookup time to the PrintServiceLookup.lookupPrintServices(...); call (with polling on, Java measures this as 0ms), but all previous attempts to force-refresh (by hacking the awt hash) added 200ms - 200,000ms.

    This seems like a perfectly viable workaround. Do you know if this affects the Windows lookup?

    @karianna that works very well.

    Specifically:

    System.setProperty("sun.java2d.print.polling", "false");

    This adds about 90ms of lookup time to the PrintServiceLookup.lookupPrintServices(...); call (with polling on, Java measures this as 0ms), but all previous attempts to force-refresh (by hacking the awt hash) added 200ms - 200,000ms.

    This seems like a perfectly viable workaround. Do you know if this affects the Windows lookup?

    Yeah, it seems really counterintuitive that setting that variable to false would speed things up. It had the same effect on Windows for me, so based on that small sample set I think you can roll out the workaround. I'll get a bug filed upstream as well.

    FYI, I ran some tests and after about 100,000 calls to PrintServiceLookup.lookupPrintServices, the delay increases (gradually) to about 1,000 ms. On my machine (i7, Quad Core) 100,000 calls took about a day.

    This still outperforms any custom refresh techniques that I'm using today, but help explains why it's true by default. In comparison, with this setting turned off, 100,000 calls to PrintServiceLookup.lookupPrintServices occurs in less than one second because there's no delay between calls.

    Another slight downside to this technique is once PrintServiceLookup.lookupPrintServices has been called, the behavior can never be toggled back off. There's no way to get the PrintServiceLookup.lookupPrintServices back to the super fast 0ms response time that it takes naturally. If the first call to PrintServiceLookup.lookupPrintServices(...) happens when sun.java2d.print.polling parameter is false, it stays that way forever -- or more accurately, until the application is restarted (80ms between calls, gradually increasing to 1,000ms)

    @karianna this is in closed status after filing upstream, but I'm not sure how I would be able to monitor the status of upstream. JDK's bug system says the following:

    Everyone with OpenJDK Author status or above has a JBS account which may be used to create and edit bugs. Those without accounts can view bugs anonymously.

    Is the expectation for the OPs to constantly monitor upstream manually?

    We are marking this issue as stale because it has not been updated for a while. This is just a way to keep the support issues queue manageable.
    It will be closed soon unless the stale label is removed by a committer, or a new comment is made.

    Just a heads-up, as the OP of the issue, I have not pushed to have it fixed upstream, since the workaround which introduces a 1 second delay after 100,000 searches is considered rarer and thus a better user experience than the current JDK behavior.

    For that reason, I have no intensions of escalating this upstream and instead will use the workaround indefinitely (or until a user's use-cases presents itself to push for a proper fix).

    So, I'm ok closing this out.

    Viable workaround:
    #3 (comment)

    Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
  •