Skip to content
Advertisement

Heap Overflow Issue when implementing and using the Printable interface

So I’ve written the class below, and it works, but we are getting some heap overflow problems when using this. The images are limited to 5 mb each. Anyone have an idea on how to solve overflowing the heap when generating the printout?

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class GeneratePrintout implements Printable {

public static void main(String... args) {
    GeneratePrintout print = new GeneratePrintout("Path to image", "Description");
    // print.setPath2("C:\images\house.jpeg");
    print.setDesc1("");
    print.setDesc2("A random house from the net");
    // print.setPath3("C:\images\biltmore.jpg");
    print.setDesc3("The Biltmore Again...");
    // print.setPath4("C:\images\house.jpeg");
    print.setDesc4("The random house again.");
    print.setType("JPG");
    print.setComments("These are pictures of two houses and this text is really long because I am trying to wrap the words, and I really hope this works correctly!");
    print.setPolNum("123456789");
    print.setContNum("2564585");
    print.setfName("John");
    print.startPrint(print);
}

private String type;
private String polNum;
private String contNum;
private String fName;
private String lName;
private String comments;
private String path1;
private String path2;
private String path3;
private String path4;
private String desc1;
private String desc2;
private String desc3;
private String desc4;

/**
 * Default Constructor.
 */
public GeneratePrintout() {
    this.setType("");
    this.setPolNum("");
    this.setContNum("");
    this.setfName("");
    this.setlName("");
    this.setComments("");
    this.setPath1("");
    this.setPath2("");
    this.setPath3("");
    this.setPath4("");
    this.setDesc1("");
    this.setDesc2("");
    this.setDesc3("");
    this.setDesc4("");
}

/**
 * Constructor.
 * 
 * @param path1
 *            The file path for the first image.
 * @param lName
 *            String last name or business name.
 */
public GeneratePrintout(String path1, String lName) {
    this.setPath1(path1);
    this.setlName(lName);
    this.setPath2("");
    this.setPath3("");
    this.setPath4("");
    this.setPolNum("");
    this.setContNum("");
    this.setfName("");
    this.setComments("");
    this.setDesc1("");
    this.setDesc2("");
    this.setDesc3("");
    this.setDesc4("");
}

/**
 * Constructor.
 * 
 * @param type
 *            image file type
 * @param polNum
 *            Policy Number
 * @param contNum
 *            Control Number.
 * @param fName
 *            First Name
 * @param lName
 *            Last Name
 * @param comments
 *            Comments
 * @param path1
 *            File path to image 1
 * @param path2
 *            File path to image 2
 * @param path3
 *            File path to image 3
 * @param path4
 *            File path to image 4
 * @param desc1
 *            Description for image 1
 * @param desc2
 *            Description for image 2
 * @param desc3
 *            Description for image 3
 * @param desc4
 *            Description for image 4
 */
public GeneratePrintout(String type, String polNum, String contNum,
        String fName, String lName, String comments, String path1, String path2,
        String path3, String path4, String desc1, String desc2, String desc3,
        String desc4) {
    this.setType(type);
    this.setPolNum(polNum);
    this.setContNum(contNum);
    this.setfName(fName);
    this.setlName(lName);
    this.setComments(comments);
    this.setPath1(path1);
    this.setPath2(path2);
    this.setPath3(path3);
    this.setPath4(path4);
    this.setDesc1(desc1);
    this.setDesc2(desc2);
    this.setDesc3(desc3);
    this.setDesc4(desc4);

}

/**
 * This method is used to start the printing process. The print dialog box
 * pops up where the user can set printer settings and then select print or
 * cancel.
 * 
 * @param printOut
 *            GeneratedPrintout object which contains the locations of the
 *            images.
 */
public void startPrint(GeneratePrintout printOut) {
    PrinterJob job = PrinterJob.getPrinterJob();
    job.setPrintable(printOut);
    // This pops up the print dialog box, this is not necessary.

    boolean doPrint = job.printDialog();

    if(doPrint){
        try{
            job.print();
        }catch(PrinterException e){
            /* The job did not successfully complete */
        }
    }
}

@Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
    /* We have only one page, and 'page' is zero-based */
    if(page > 0){
        return NO_SUCH_PAGE;
    }
    // Find the printable area of the printer.
    /*
     * (0,0) is typically outside the imageable area, so we must translate
     * by the X and Y values in the PageFormat to avoid clipping
     */
    Graphics2D g2d = (Graphics2D) g;
    g2d.translate(pf.getImageableX(), pf.getImageableY());
    // Get default width, height, x and y values of the page.
    int width = (int) pf.getImageableWidth();
    int height = (int) pf.getImageableHeight();
    int x = (int) pf.getImageableX();
    int y = (int) pf.getImageableY();

    Image img1 = null;
    Image img2 = null;
    Image img3 = null;
    Image img4 = null;

    // Try to create the images from the specified filepaths. Image 1 throws
    // a NullPointerException if not found because it is required.
    try{
        if(!"".equals(path1)){
            File src1 = new File(path1);
            img1 = ImageIO.read(src1);
        }else{
            throw new NullPointerException("File path 1 is required.");
        }
        if(!"".equals(path2)){
            File src2 = new File(path2);
            img2 = ImageIO.read(src2);
        }
        if(!"".equals(path3)){
            File src3 = new File(path3);
            img3 = ImageIO.read(src3);
        }
        if(!"".equals(path4)){
            File src4 = new File(path4);
            img4 = ImageIO.read(src4);
        }
    }catch(IOException e){
        e.printStackTrace();
    }

    /* Now we perform our rendering */
    // Note: Image 1 must exist before image 2, and image 2 must exist
    // before image 3 and so on.
    // Image 1 and its description.
    if(img1 != null){
        img1 = img1.getScaledInstance(width / 2, height / 4, 0);
        g.drawImage(img1, x, y, null);
        g.drawString(desc1, x, y + img1.getHeight(null) + 10);
    }
    // Image 2 and its description.
    if(img1 != null && img2 != null){
        img2 = img2.getScaledInstance(width / 2, height / 4, 0);
        g.drawImage(img2, x + img1.getWidth(null) + 10, y, null);
        g.drawString(desc2, x + (width / 2) + 10, y + img2.getHeight(null) + 10);
    }
    // Image 3 and its description.
    if(img1 != null && img2 != null && img3 != null){
        img3 = img3.getScaledInstance(width / 2, height / 4, 0);
        g.drawImage(img3, x, y + img1.getHeight(null) + 20, null);
        g.drawString(desc3, x, y + img1.getHeight(null) + img3.getHeight(null)
                + 30);

    }
    // Image 4 and its description.
    if(img1 != null && img2 != null && img3 != null && img4 != null){
        img4 = img4.getScaledInstance(width / 2, height / 4, 0);
        g.drawImage(img4, x + img3.getWidth(null) + 10, y + img2.getHeight(null)
                + 20, null);
        g.drawString(desc4, x + (width / 2) + 10, y + img1.getHeight(null)
                + img3.getHeight(null) + 30);
    }
    // This is used to draw the text at the bottom.
    int p1Height = height;

    if(img1 != null){
        p1Height = y + img1.getHeight(null) + 50;
    }
    if(img3 != null){
        p1Height = y + img1.getHeight(null) + img3.getHeight(null) + 50;
    }

    // Left panel
    g.drawString("Image Type: " + type, x, p1Height);

    //Wordwrap business name.
    String[] busArray = lName.split(" ");
    int addY = 20;
    int check = 0;
    for(int i = 0; i < busArray.length;){
        String toAdd = "";
        if(addY == 20)
            toAdd +="Last or Business Name: ";
        //Only allow a max of 45 characters per line.
        while(toAdd.length() <= 45 && i < busArray.length){
            toAdd += busArray[i] + " ";
            i++;
        }
        g.drawString(toAdd, x, p1Height + addY);
        check = addY;
        addY += 13;
        toAdd = "";
    }
    addY += 13;

    // Wordwrap the comments section
    String[] commentsArray = comments.split(" ");
    for(int i = 0; i < commentsArray.length;){
        String toAdd = "";
        if((addY - check) == 26)
            toAdd += "Comments: ";
        // Only allow a max of 45 characters per line.
        while(toAdd.length() <= 45 && i < commentsArray.length){
            toAdd += commentsArray[i] + " ";
            i++;
        }

        g.drawString(toAdd, x, p1Height + addY);
        // Add 13 pixels to Y to create a new line.
        addY += 13;
        toAdd = "";
    }

    // right Panel
    g.drawString("Policy #: " + polNum, width / 2, p1Height);
    g.drawString("Control #: " + contNum, width / 2, p1Height + 20);
    g.drawString("First Name: " + fName, width / 2, p1Height + 40);

    /* tell the caller that this page is part of the printed document */
    return PAGE_EXISTS;
}

/**
 * @param type
 *            the type to set
 */
public void setType(String type) {
    this.type = type;
}

/**
 * @return the type
 */
public String getType() {
    return type;
}

/**
 * @param polNum
 *            the polNum to set
 */
public void setPolNum(String polNum) {
    this.polNum = polNum;
}

/**
 * @return the polNum
 */
public String getPolNum() {
    return polNum;
}

/**
 * @param contNum
 *            the contNum to set
 */
public void setContNum(String contNum) {
    this.contNum = contNum;
}

/**
 * @return the contNum
 */
public String getContNum() {
    return contNum;
}

/**
 * @param fName
 *            the fName to set
 */
public void setfName(String fName) {
    this.fName = fName;
}

/**
 * @return the fName
 */
public String getfName() {
    return fName;
}

/**
 * @param lName
 *            the lName to set
 */
public void setlName(String lName) {
    this.lName = lName;
}

/**
 * @return the lName
 */
public String getlName() {
    return lName;
}

/**
 * @param comments
 *            the comments to set
 */
public void setComments(String comments) {
    this.comments = comments;
}

/**
 * @return the comments
 */
public String getComments() {
    return comments;
}

/**
 * @param desc2
 *            the desc2 to set
 */
public void setDesc2(String desc2) {
    this.desc2 = desc2;
}

/**
 * @return the desc2
 */
public String getDesc2() {
    return desc2;
}

/**
 * @param desc3
 *            the desc3 to set
 */
public void setDesc3(String desc3) {
    this.desc3 = desc3;
}

/**
 * @return the desc3
 */
public String getDesc3() {
    return desc3;
}

/**
 * @param desc4
 *            the desc4 to set
 */
public void setDesc4(String desc4) {
    this.desc4 = desc4;
}

/**
 * @return the desc4
 */
public String getDesc4() {
    return desc4;
}

/**
 * @param path1
 *            the path1 to set
 */
public void setPath1(String path1) {
    this.path1 = path1;
}

/**
 * @return the path1
 */
public String getPath1() {
    return path1;
}

/**
 * @param path2
 *            the path2 to set
 */
public void setPath2(String path2) {
    this.path2 = path2;
}

/**
 * @return the path2
 */
public String getPath2() {
    return path2;
}

/**
 * @param path3
 *            the path3 to set
 */
public void setPath3(String path3) {
    this.path3 = path3;
}

/**
 * @return the path3
 */
public String getPath3() {
    return path3;
}

/**
 * @param path4
 *            the path4 to set
 */
public void setPath4(String path4) {
    this.path4 = path4;
}

/**
 * @return the path4
 */
public String getPath4() {
    return path4;
}

/**
 * @param desc1
 *            the desc1 to set
 */
public void setDesc1(String desc1) {
    this.desc1 = desc1;
}

/**
 * @return the desc1
 */
public String getDesc1() {
    return desc1;
}

}

Advertisement

Answer

Without going in the specifics of your code, maybe you really need a bigger heap size to do this task. Have you tried increasing it with the flag -Xmx?

-Xmx<size>        set maximum Java heap size

For instance:

java -Xmx360m ...

sets the heap size to 360 Mb.

Alternatively, you can use a profiler to understand where the memory is used. See this tutorial for Eclipse.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement