0

my problem is when I try to display pdf in my JavaFX app, the pages load fast when I run from the ide

but its to slow and show not respond, I set the heap to 3000mp without any difference

I use the **PDFViewerFX **library in my project and edit the buffering code to enhance performance,

it's faster now in ide but nothing improved on the jar file,

what could be the difference running in ide or jar?

hear is the code to display pdf

    public void loadPDF(URL url) throws IOException {
        loadPDF(new BufferedInputStream(url.openConnection().getInputStream()));
    }
    private static final Logger logger = LoggerFactory.getLogger(PDFDisplayer.class);
    private static final int THREAD_POOL_SIZE = 5;

    private static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(THREAD_POOL_SIZE, new ThreadFactory() {
        private final ThreadGroup group = new ThreadGroup("my-thread-pool");
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, "my-thread-" + new AtomicInteger(1), 0);
            t.setDaemon(false);
            return t;
        }
    });


    private final ObjectProperty<Consumer<Task<String>>> onLoaderTaskPresent =
            new SimpleObjectProperty<>();

    private boolean pdfJsLoaded;
    public void loadPDF(InputStream inputStream) {
        if (inputStream == null)
            return;

        Task<String> task = buildLoadingTask(inputStream);

        final Consumer<Task<String>> onLoaderTaskPresent = this.onLoaderTaskPresent.get();
        if (onLoaderTaskPresent != null) {
            Platform.runLater(() -> onLoaderTaskPresent.accept(task));
        }
        THREAD_POOL.submit(task);
    }

    /**
     * @deprecated Use {@link #loadPDF(InputStream)} instead
     */
    @Deprecated
    public void displayPdf(InputStream inputStream) throws IOException {
        loadPDF(inputStream);
    }
    private void loadInputStream(InputStream inputStream) {
        Task<String> loadingTask = buildLoadingTask(inputStream);
        THREAD_POOL.submit(loadingTask);
        loadingTask.setOnSucceeded(event -> {
            String js = loadingTask.getValue();
            if (js != null) {
                try {
                    webView.getEngine().executeScript(js);
                } catch (Exception ex) {
                    if (!pdfJsLoaded) {
                        loadScript = js;
                    }
                }
            }
            THREAD_POOL.shutdown();
        });
        loadingTask.setOnFailed(event -> {
            Throwable ex = event.getSource().getException();
            if (ex != null) {
                // Handle error more gracefully
                showErrorDialog("Failed to execute script", (Exception) ex);
            }
        });
    }


    private Task<String> buildLoadingTask(InputStream inputStream) {
        final Task<String> task = new Task<String>() {
            @Override
            protected String call() throws Exception {
                try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

                    long contentSize = inputStream.available();
                    long onePercent = contentSize / 100;

                    int allReadBytesCount = 0;

                    byte[] buf = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buf)) >= 0) {
                        allReadBytesCount += bytesRead;
                        outputStream.write(buf, 0, bytesRead);

                        if (onePercent > 0) {
                            double percent = allReadBytesCount / (double) onePercent;
                            updateProgress(percent, 100d);
                        }

                        if (this.isCancelled()) {
                            return null;
                        }
                    }

                    byte[] data = outputStream.toByteArray();
                    String base64 = Base64.getEncoder().encodeToString(data);

                    //JS Function declaration
                    return "openFileFromBase64('" + base64 + "');";
                } finally {
                    inputStream.close();
                }
            }
        };
        task.valueProperty().addListener((observable, oldValue, js) -> {
            if (js != null) {
                try {
                    webView.getEngine().executeScript(js);
                } catch (Exception ex) {
                    if (!pdfJsLoaded) loadScript = js;
                }
            }
        });
        return task;
    }
    @SuppressWarnings("all")
    public void setSecondaryToolbarToggleVisibility(boolean value) {
        setVisibilityOf("secondaryToolbarToggle", value);

        String js;
        if (value){
            js = new StringBuilder()
                    .append("var element = document.getElementsByClassName('verticalToolbarSeparator')[0];")
                    .append("element.style.display = 'inherit';")
                    .append("element.style.visibility = 'inherit';")
                    .toString();
        } else {
            js = new StringBuilder()
                    .append("var element = document.getElementsByClassName('verticalToolbarSeparator')[0];")
                    .append("element.style.display = 'none';")
                    .append("element.style.visibility = 'hidden';")
                    .toString();
        }

        try {
            webView.getEngine().executeScript(js);
        } catch (Exception ex){
            if (!pdfJsLoaded) toExecuteWhenPDFJSLoaded += js;
        }
    }

    @SuppressWarnings("all")
    public void setVisibilityOf(String id, boolean value){
        String css;
        if (value) {
            css = new StringBuilder()
                    .append("document.getElementById('" + id + "').style.display = 'inherit';")
                    .append("document.getElementById('" + id + "').style.visibility = 'inherit';")
                    .toString();
        } else {
            css = new StringBuilder()
                    .append("document.getElementById('" + id + "').style.display = 'none';")
                    .append("document.getElementById('" + id + "').style.visibility = 'hidden';")
                    .toString();
        }

        try {
            webView.getEngine().executeScript(css);
        } catch (Exception ex) {
            if (!pdfJsLoaded) this.toExecuteWhenPDFJSLoaded += css;
        }
    }

    public int getActualPageNumber(){
        try {
            return (int) webView.getEngine().executeScript("PDFViewerApplication.page;");
        } catch (Exception e) {
            return 0;
        }
    }
    private void showErrorDialog(String message, Exception ex) {
        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setTitle("Error");
        alert.setHeaderText(message);
        alert.setContentText(ex.getMessage());
        alert.showAndWait();
    }
    public int getTotalPageCount(){
        try {
            return (int) webView.getEngine().executeScript("PDFViewerApplication.pagesCount;");
        } catch (Exception e) {
            return 0;
        }
    }

    public void navigateByPage(int pageNum) {
        String jsCommand = "goToPage(" + pageNum + ");";
        try {
            webView.getEngine().executeScript(jsCommand);
        } catch (Exception ex) {
            if (!pdfJsLoaded) toExecuteWhenPDFJSLoaded += jsCommand;
        }
    }

    public void executeScript(String js) {
        try {
            this.webView.getEngine().executeScript(js);
        } catch (Exception ex) {
            if (!pdfJsLoaded) toExecuteWhenPDFJSLoaded += String.format("%s;", js);
        }
    }

    private WebView createWebView() {
        WebView webView = new WebView();
        webView.setContextMenuEnabled(false);

        WebEngine engine = webView.getEngine();
String url;
      try {
            URL resourceUrl = getClass().getResource("/pdfjs_2.2.228/web/viewer.html");
        engine.setJavaScriptEnabled(true);
        engine.load(resourceUrl.toString());

      } catch (Exception e1) {
         // TODO Auto-generated catch block
         e1.printStackTrace();
      }
        engine.getLoadWorker()
                .stateProperty()
                .addListener(
                        new ChangeListener<Worker.State>() {
                            @Override
                            public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
                                JSObject window = (JSObject) engine.executeScript("window");
                                window.setMember("java", new JSLogListener());

                                if (newValue == Worker.State.SUCCEEDED) {
                                    try {
                                       pdfJsLoaded = true;

                                        if (loadScript != null) {
                                            logger.debug("PDF already loaded");
                                            engine.executeScript(loadScript);
                                        }

                                        engine.executeScript(toExecuteWhenPDFJSLoaded);
                                        toExecuteWhenPDFJSLoaded = null;
                                        observable.removeListener(this);
                                    } catch (Exception e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                            }
                        });
        return webView;
    }

    public Parent toNode() {
        if (webView == null)
            return webView = createWebView();
        else
            return webView;
    }

I used Marven and artifact with jest dependency I used and the performance are the same

I use openjdk18 and oracle jdk18 the same result

  • Where does the pdf come from? How large is it in bytes and pages? Are you using the same Java and library versions in the command line as the IDE? If you load the pdf in a browser using `pdf.js` is it also slow? If not, you could show the pdf in a browser rather than an embedded web view. Probably you won’t get much help here. You will need to profile the app and see why it is slow (which may be difficult given a lot of the work is in JavaScript in WebView). – jewelsea Mar 13 '23 at 05:15
  • I need to impeded a pdf viewer in my java, Small pdf its slower but its ok but 35mb file start not responding, i check in profiler isee 3 threads from thread pool when run in ide , but in jar its 1, in tasks manager cpu utilisation gos to 70% where in jar the max i see 30 to 50, what could be the difference in ide thes problem made me comb my hair – Ahmad Luay AlQatu Mar 13 '23 at 09:32

1 Answers1

-1

it works smoothly when I extract the jar and run the main.class from cmd like this

java -cp ./pdfcheck-1.0  pdfcheck.main

I said this is most likely how the ide run my code. any explanation of what happened and why?

Roshin Raphel
  • 2,612
  • 4
  • 22
  • 40
  • That doesn't look like the right way to run a JavaFX application. The JavaFX modules should be on the module path, not the class path, see [https://openjfx.io](https://openjfx.io/openjfx-docs/). I'm not saying that this is related to your performance issue. – jewelsea Mar 13 '23 at 21:45
  • all desinences and JavaFX are embedded in jar, I use -cp to run the main class – Ahmad Luay AlQatu Mar 13 '23 at 23:08
  • That is an [unsupported configuration](https://stackoverflow.com/questions/67854139/javafx-warning-unsupported-javafx-configuration-classes-were-loaded-from-unna), but if it is working for you at the moment, then I guess OK . . . – jewelsea Mar 14 '23 at 00:05