Skip to content

Commit

Permalink
7001133: OutOfMemoryError by CustomMediaSizeName implementation
Browse files Browse the repository at this point in the history
Reviewed-by: psadhukhan
  • Loading branch information
Alexander Scherbatiy committed Dec 18, 2023
1 parent ecff9c1 commit 10335f6
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 20 deletions.
56 changes: 56 additions & 0 deletions src/java.desktop/share/classes/sun/print/CustomMediaSizeName.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,20 @@

import java.io.Serial;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;

import javax.print.attribute.EnumSyntax;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaSize;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.Size2DSyntax;

class CustomMediaSizeName extends MediaSizeName {
private static ArrayList<String> customStringTable = new ArrayList<>();
private static ArrayList<MediaSizeName> customEnumTable = new ArrayList<>();
private static Map<SizeNameChoiceItem, CustomMediaSizeName> customMap = new HashMap<>();
private String choiceName;
private MediaSizeName mediaName;

Expand Down Expand Up @@ -191,4 +196,55 @@ protected EnumSyntax[] getEnumValueTable() {
return customEnumTable.toArray(enumTable);
}

public static CustomMediaSizeName create(String name, String choice,
float width, float length) {
SizeNameChoiceItem key = new SizeNameChoiceItem(name, choice, width, length);
CustomMediaSizeName value = customMap.get(key);
if (value == null) {
value = new CustomMediaSizeName(name, choice, width, length);
customMap.put(key, value);

// add this new custom media size name to MediaSize array
if ((width > 0.0) && (length > 0.0)) {
try {
new MediaSize(width, length, Size2DSyntax.INCH, value);
} catch (IllegalArgumentException e) {
/* PDF printer in Linux for Ledger paper causes
"IllegalArgumentException: X dimension > Y dimension".
We rotate based on IPP spec. */
new MediaSize(length, width, Size2DSyntax.INCH, value);
}
}
}
return value;
}

private static class SizeNameChoiceItem {

private final String name;
private final String choice;
private final float width;
private final float length;

public SizeNameChoiceItem(String name, String choice, float width, float length) {
this.name = name;
this.choice = choice;
this.width = width;
this.length = length;
}

public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
SizeNameChoiceItem that = (SizeNameChoiceItem) object;
return Objects.equals(this.name, that.name)
&& Objects.equals(this.choice, that.choice) &&
Float.compare(this.width, that.width) == 0 &&
Float.compare(this.length, that.length) == 0;
}

public int hashCode() {
return Objects.hash(name, choice, width, length);
}
}
}
36 changes: 36 additions & 0 deletions src/java.desktop/share/classes/sun/print/CustomMediaTray.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

import java.io.Serial;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Map;
import java.util.HashMap;

import javax.print.attribute.EnumSyntax;
import javax.print.attribute.standard.Media;
Expand All @@ -35,6 +38,7 @@
public class CustomMediaTray extends MediaTray {
private static ArrayList<String> customStringTable = new ArrayList<>();
private static ArrayList<MediaTray> customEnumTable = new ArrayList<>();
private static Map<NameChoiceItem, CustomMediaTray> customMap = new HashMap<>();
private String choiceName;

private CustomMediaTray(int x) {
Expand Down Expand Up @@ -93,4 +97,36 @@ protected EnumSyntax[] getEnumValueTable() {
return customEnumTable.toArray(enumTable);
}

public static CustomMediaTray create(String name, String choice) {
NameChoiceItem key = new NameChoiceItem(name, choice);
CustomMediaTray value = customMap.get(key);
if (value == null) {
value = new CustomMediaTray(name, choice);
customMap.put(key, value);
}
return value;
}

private static class NameChoiceItem {

private final String name;
private final String choice;

public NameChoiceItem(String name, String choice) {
this.name = name;
this.choice = choice;
}

public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
NameChoiceItem that = (NameChoiceItem) object;
return Objects.equals(this.name, that.name)
&& Objects.equals(this.choice, that.choice);
}

public int hashCode() {
return Objects.hash(name, choice);
}
}
}
21 changes: 4 additions & 17 deletions src/java.desktop/unix/classes/sun/print/CUPSPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,26 +225,13 @@ private synchronized void initMedia() {
w = (float)(pageSizes[i*6+4]/PRINTER_DPI);
y = (float)(pageSizes[i*6+5]/PRINTER_DPI);

msn = new CustomMediaSizeName(media[i*2], media[i*2+1],
width, length);
msn = CustomMediaSizeName.create(media[i*2], media[i*2+1],
width, length);

// add to list of standard MediaSizeNames
if ((cupsMediaSNames[i] = msn.getStandardMedia()) == null) {
// add custom if no matching standard media
cupsMediaSNames[i] = msn;

// add this new custom msn to MediaSize array
if ((width > 0.0) && (length > 0.0)) {
try {
new MediaSize(width, length,
Size2DSyntax.INCH, msn);
} catch (IllegalArgumentException e) {
/* PDF printer in Linux for Ledger paper causes
"IllegalArgumentException: X dimension > Y dimension".
We rotate based on IPP spec. */
new MediaSize(length, width, Size2DSyntax.INCH, msn);
}
}
}

// add to list of custom MediaSizeName
Expand All @@ -269,8 +256,8 @@ private synchronized void initMedia() {

MediaTray mt;
for (int i=0; i<nTrays; i++) {
mt = new CustomMediaTray(media[(nPageSizes+i)*2],
media[(nPageSizes+i)*2+1]);
mt = CustomMediaTray.create(media[(nPageSizes+i)*2],
media[(nPageSizes+i)*2+1]);
cupsMediaTrays[i] = mt;
}

Expand Down
6 changes: 3 additions & 3 deletions src/java.desktop/unix/classes/sun/print/IPPPrintService.java
Original file line number Diff line number Diff line change
Expand Up @@ -1013,15 +1013,15 @@ public CustomMediaSizeName findCustomMedia(MediaSizeName media) {
* Returns the matching standard Media using string comparison of names.
*/
private Media getIPPMedia(String mediaName) {
CustomMediaSizeName sampleSize = new CustomMediaSizeName("sample", "",
0, 0);
CustomMediaSizeName sampleSize =
CustomMediaSizeName.create("sample", "", 0, 0);
Media[] sizes = sampleSize.getSuperEnumTable();
for (int i=0; i<sizes.length; i++) {
if (mediaName.equals(""+sizes[i])) {
return sizes[i];
}
}
CustomMediaTray sampleTray = new CustomMediaTray("sample", "");
CustomMediaTray sampleTray = CustomMediaTray.create("sample", "");
Media[] trays = sampleTray.getSuperEnumTable();
for (int i=0; i<trays.length; i++) {
if (mediaName.equals(""+trays[i])) {
Expand Down
61 changes: 61 additions & 0 deletions test/jdk/javax/print/CustomMediaSizeNameOOMETest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, BELLSOFT. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 7001133
* @summary OutOfMemoryError by CustomMediaSizeName implementation
* @run main CustomMediaSizeNameOOMETest
* @run main/timeout=300/othervm -Xmx8m CustomMediaSizeNameOOMETest
*/

import javax.print.PrintService;
import javax.print.PrintServiceLookup;

public class CustomMediaSizeNameOOMETest {

private static final int MILLIS = 3000;

public static void main(String[] args) {

PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
if (services == null || services.length == 0) {
return;
}

for (PrintService service : services) {
service.getUnsupportedAttributes(null, null);
}

long time = System.currentTimeMillis() + MILLIS;

do {
for (int i = 0; i < 2000; i++) {
for (PrintService service : services) {
service.getAttributes();
}
}
} while (time > System.currentTimeMillis());
}
}

3 comments on commit 10335f6

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderScherbatiy
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk21u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on 10335f6 Mar 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderScherbatiy the backport was successfully created on the branch backport-AlexanderScherbatiy-10335f60 in my personal fork of openjdk/jdk21u-dev. To create a pull request with this backport targeting openjdk/jdk21u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit 10335f60 from the openjdk/jdk repository.

The commit being backported was authored by Alexander Scherbatiy on 18 Dec 2023 and was reviewed by Prasanta Sadhukhan.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk21u-dev:

$ git fetch https://github.com/openjdk-bots/jdk21u-dev.git backport-AlexanderScherbatiy-10335f60:backport-AlexanderScherbatiy-10335f60
$ git checkout backport-AlexanderScherbatiy-10335f60
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk21u-dev.git backport-AlexanderScherbatiy-10335f60

Please sign in to comment.