Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

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

Temporary font files are not deleted on Windows #505

Open
Phillipus opened this issue Jan 12, 2025 · 5 comments
Open

Temporary font files are not deleted on Windows #505

Phillipus opened this issue Jan 12, 2025 · 5 comments

Comments

@Phillipus
Copy link

Phillipus commented Jan 12, 2025

(With reference to #337)

Jasper Reports 6.21.4
Windows 11 Pro, 24H2, 26100.2605
OpenJDK Temurin-17.0.13+11 and 21.0.5+11

Since JR version 6.13.0 temporary font files are created in the user's temp directory but are not deleted on exit. This is not a problem on Mac or Linux, only Windows.

I've provided a standalone test case to show this:

JasperTest.zip

The code is this:

import java.io.File;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperReport;

public class JasperTest {
    
    static class ExampleDataSource implements JRDataSource {

        @Override
        public boolean next() throws JRException {
            return false;
        }

        @Override
        public Object getFieldValue(JRField jrField) throws JRException {
            return "Test";
        }
    }

    public static void main(String[] args) {
        try {
            File reportFile = new File("report.jrxml");
            JasperReport jrReport = JasperCompileManager.compileReport(reportFile.getAbsolutePath());
            JasperFillManager.fillReport(jrReport, null, new ExampleDataSource());
        }
        catch(JRException ex) {
            ex.printStackTrace();
        }
    }
}
  1. Unzip the attached zip project on Windows
  2. From the Windows command line run this:
    java -cp jasperreports-6.21.4.jar;commons-digester-2.1.jar;commons-logging-1.3.4.jar;commons-collections4-4.4.jar;commons-beanutils-1.10.0.jar JasperTest.java
  3. Note that in the temporary directory (C:\Users\username\AppData\Local\Temp) that there are two font files of the form jr-font123456789123456789.ttf
  4. Run the example again and note two more font files are created

In our real world use of JR more than two temporary font files are created at a time and remain in the temp folder (around 20) and after a few invocations of JR code there could be thousands.

It seems that font files that are created in AwtFontManager are marked to be deleted on exit:

https://github.com/TIBCOSoftware/jasperreports/blob/4df899783f6198a3e7479948356a8a7b75294603/core/src/main/java/net/sf/jasperreports/engine/fonts/AwtFontManager.java#L79-L80

However, when Java calls its method to delete files on exit (in java.io.DeleteOnExitHook), these files are locked and cannot be deleted (File#delete returns false).

@Phillipus
Copy link
Author

Phillipus commented Jan 12, 2025

I've narrowed it down even further and traced it to this line:

https://github.com/TIBCOSoftware/jasperreports/blob/4df899783f6198a3e7479948356a8a7b75294603/core/src/main/java/net/sf/jasperreports/engine/fonts/AwtFontManager.java#L89

It seems that Font.createFont(Font.TRUETYPE_FONT, file) locks the file somewhere so it can't be deleted on exit.

Here's a simple test (provide a font called "font.ttf"):

import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.IOException;

public class FileDeleteTest {
    
    public static void main(String[] args) {
        try {
            File fontFile = new File("font.ttf");
            fontFile.deleteOnExit(); // File is not deleted on exit

            Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
        }
        catch(FontFormatException | IOException ex) {
            ex.printStackTrace();
        }
    }
}

However, if an input stream is used instead of a File the file can be deleted:

import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileDeleteTest {
    
    public static void main(String[] args) {
        try {
            File fontFile = new File("font.ttf");
            fontFile.deleteOnExit(); // File is deleted on exit

            try(FileInputStream stream = new FileInputStream(fontFile)) {
                Font font = Font.createFont(Font.TRUETYPE_FONT, stream);
            }
        }
        catch(FontFormatException | IOException ex) {
            ex.printStackTrace();
        }
    }
}

@Phillipus
Copy link
Author

So, perhaps a fix in AwtFontManager.java would be to use something like this:

Font font = null;
          
try(FileInputStream stream = new FileInputStream(fontFile.toFile())) {
    font = Font.createFont(Font.TRUETYPE_FONT, stream);
}

Phillipus added a commit to archimatetool/archi that referenced this issue Jan 12, 2025
- Unfortunately, we can't use the latest version (currently 6.21.4) because version 6.13 and later doesn't delete the "jr-fontXXXXXXXXXXXXXX.ttf" temporary font files in the temp folder on exit on Windows. See Jaspersoft/jasperreports#505

- If we ever do use a later version we should only need to update jasperreports-x.x.x.jar and jasperreports-fonts-x.x.x.jar

- Note that we now use openpdf-x.x.x.jar rather than itext-x.x.x.jar
@dadza
Copy link
Collaborator

dadza commented Jan 13, 2025

When creating a Font with the InputStream method, do you see files called ~+JF*.tmp created in the temp folder?

Initially JasperReports was using the InputStream method (see 2c5eb44), but there were probelems with the ~+JF*.tmp files created internally by java.awt.Font.

@Phillipus
Copy link
Author

Phillipus commented Jan 13, 2025

When creating a Font with the InputStream method, do you see files called ~+JF*.tmp created in the temp folder?

No. My suggestion is to use an input stream on these new temp files, not an input stream on the original file in the jar file.

Edit - see next comment.

Phillipus added a commit to archimatetool/archi that referenced this issue Jan 13, 2025
- Unfortunately, we can't use the latest version (currently 6.21.4) because version 6.13 and later doesn't delete the "jr-fontXXXXXXXXXXXXXX.ttf" temporary font files in the temp folder on exit on Windows. See Jaspersoft/jasperreports#505

- If we ever do use a later version we should only need to update jasperreports-x.x.x.jar and jasperreports-fonts-x.x.x.jar

- Note that we now use openpdf-x.x.x.jar rather than itext-x.x.x.jar
@Phillipus
Copy link
Author

Phillipus commented Jan 13, 2025

When creating a Font with the InputStream method, do you see files called ~+JF*.tmp created in the temp folder?

No. My suggestion is to use an input stream on these new temp files, not an input stream on the original file in the jar file.

Sorry, I'm wrong. Yes these ~+JF*.tmp are created. But they are deleted on exit.

I guess the changes to AwtFontManager were to avoid these files being created. However the problem now is that some of the temporary files that are created now are not deleted on exit on Windows leading to potentially many thousands taking up disk space. I wonder if Windows JR users have checked their temp folder lately?

Phillipus added a commit to archimatetool/archi that referenced this issue Jan 13, 2025
- Use 6.2.14 jars
- Add workaround to delete temporary font files when starting this plug-in
- We can't delete them on exit
- See Jaspersoft/jasperreports#505
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 13, 2025
- Unfortunately, we can't use the latest version (currently 6.21.4) because version 6.13 and later doesn't delete the "jr-fontXXXXXXXXXXXXXX.ttf" temporary font files in the temp folder on exit on Windows. See Jaspersoft/jasperreports#505

- If we ever do use a later version we should only need to update jasperreports-x.x.x.jar and jasperreports-fonts-x.x.x.jar

- Note that we now use openpdf-x.x.x.jar rather than itext-x.x.x.jar
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 13, 2025
- Use 6.2.14 jars
- Add workaround to delete temporary font files when starting this plug-in
- We can't delete them on exit
- See Jaspersoft/jasperreports#505
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 14, 2025
- Use 6.21.4 jars
- Add workaround to delete temporary font files when starting this plug-in
- We can't delete them on exit
- See Jaspersoft/jasperreports#505
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 15, 2025
- Unfortunately, we can't use the latest version (currently 6.21.4) because version 6.13 and later doesn't delete the "jr-fontXXXXXXXXXXXXXX.ttf" temporary font files in the temp folder on exit on Windows. See Jaspersoft/jasperreports#505

- If we ever do use a later version we should only need to update jasperreports-x.x.x.jar and jasperreports-fonts-x.x.x.jar

- Note that we now use openpdf-x.x.x.jar rather than itext-x.x.x.jar
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 15, 2025
- Use 6.21.4 jars
- Add workaround to delete temporary font files when starting this plug-in
- We can't delete them on exit
- See Jaspersoft/jasperreports#505
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 15, 2025
- Unfortunately, we can't use the latest version (currently 6.21.4) because version 6.13 and later doesn't delete the "jr-fontXXXXXXXXXXXXXX.ttf" temporary font files in the temp folder on exit on Windows. See Jaspersoft/jasperreports#505

- If we ever do use a later version we should only need to update jasperreports-x.x.x.jar and jasperreports-fonts-x.x.x.jar

- Note that we now use openpdf-x.x.x.jar rather than itext-x.x.x.jar
Phillipus added a commit to archimatetool/archi that referenced this issue Jan 15, 2025
- Use 6.21.4 jars
- Add workaround to delete temporary font files when starting this plug-in
- We can't delete them on exit
- See Jaspersoft/jasperreports#505
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants