java - "java.lang.OutOfMemoryError: Java heap space"在 ColdFusion 11 中使用 ImageReadBase64() 读取大图像时

标签 java image-processing coldfusion base64 coldfusion-11

我在 ColdFusion 11 中内置了一个简单的 REST API,它允许我们的供应商更新产品信息。他们发送的大部分数据(大约 30 个属性)都是简单的值——字符串和数字。一个属性是代表图像文件的 Base64 编码字符串。 REST API 更新数据库中的简单数据值,然后读取图像并将其调整为适合在网站上使用的 4 种大小。我注意到供应商偶尔会发送一些请求(20MB+)的大图像,并且这些请求通常会在 ImageReadBase64() 所在的行上导致“java.lang.OutOfMemoryError: Java heap space”。函数被调用。我们在这台服务器上运行了其他网络应用程序,似乎在处理这些图像时被锁定的内存也会导致这些应用程序出现问题。我试图弄清楚代码中是否有任何我可以做的事情来减少这些问题,即使它正在想办法在图像“太大”(超过一定大小)时不处理它们。这是运行以处理图像的所有代码:

public struct function getDimensionsToEnlarge(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric minWidth,
    required numeric minHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    if  (   ARGUMENTS.minHeight > 0
        &&  ARGUMENTS.minWidth > 0
        &&  ARGUMENTS.imageHeight < ARGUMENTS.minHeight
        &&  ARGUMENTS.imageWidth < ARGUMENTS.minWidth
        ) {
        LOCAL.Dimensions.width=ARGUMENTS.minWidth;
        LOCAL.Dimensions.height=ARGUMENTS.minHeight;
    }

    return LOCAL.Dimensions;
}

public struct function getDimensionsToShrink(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric maxWidth,
    required numeric maxHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    if  (   ARGUMENTS.maxHeight > 0
        &&  ARGUMENTS.maxWidth > 0
        &&  (   ARGUMENTS.imageHeight > ARGUMENTS.maxHeight
            ||  ARGUMENTS.imageWidth > ARGUMENTS.maxWidth
            )
        ) {
        LOCAL.Dimensions.width=ARGUMENTS.maxWidth;
        LOCAL.Dimensions.height=ARGUMENTS.maxHeight;
    }

    return LOCAL.Dimensions;
}

public struct function getDimensionsToFit(
    required numeric imageWidth,
    required numeric imageHeight,
    required numeric minWidth,
    required numeric minHeight,
    required numeric maxWidth,
    required numeric maxHeight
    ) {
    LOCAL.Dimensions={
        width=-1,
        height=-1
        };

    LOCAL.Dimensions =
        getDimensionsToEnlarge(
            imageHeight=ARGUMENTS.imageHeight,
            imageWidth=ARGUMENTS.imageWidth,
            minWidth=ARGUMENTS.minWidth,
            minHeight=ARGUMENTS.minHeight
            );

    if (LOCAL.Dimensions.width < 0 && LOCAL.Dimensions.height < 0)
        LOCAL.Dimensions =
            getDimensionsToShrink(
                imageHeight=ARGUMENTS.imageHeight,
                imageWidth=ARGUMENTS.imageWidth,
                maxWidth=ARGUMENTS.maxWidth,
                maxHeight=ARGUMENTS.maxHeight
                );

    return LOCAL.Dimensions;
}

public any function scale(
    required any image,
    string action="fit",
    numeric minWidth=-1,
    numeric minHeight=-1,
    numeric maxWidth=-1,
    numeric maxHeight=-1
    ) {
    LOCAL.Dimensions={
            width=-1,
            height=-1
        };
    LOCAL.Image=Duplicate(ARGUMENTS.image);

    switch (ARGUMENTS.action) {
        case "shrink":
            LOCAL.Dimensions =
                getDimensionsToShrink(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    maxWidth=ARGUMENTS.maxWidth,
                    maxHeight=ARGUMENTS.maxHeight
                );

            break;
        case "enlarge":
            LOCAL.Dimensions =
                getDimensionsToEnlarge(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    minWidth=ARGUMENTS.minWidth,
                    minHeight=ARGUMENTS.minHeight
                );

            break;
        default:
            LOCAL.Dimensions =
                getDimensionsToFit(
                    imageHeight=LOCAL.Image.getHeight(),
                    imageWidth=LOCAL.Image.getWidth(),
                    minWidth=ARGUMENTS.minWidth,
                    minHeight=ARGUMENTS.minHeight,
                    maxWidth=ARGUMENTS.maxWidth,
                    maxHeight=ARGUMENTS.maxHeight
                );

            break;
    }

    if (LOCAL.Dimensions.width > 0 && LOCAL.Dimensions.height > 0) {
        ImageSetAntialiasing(LOCAL.Image, "on");

        ImageScaleToFit(
            LOCAL.Image,
            LOCAL.Dimensions.width,
            LOCAL.Dimensions.height
            );
    }

    return LOCAL.Image;
}

public void function createLargeThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=500, maxWidth=700),
        getLargeImagePath(),
        0.75,
        true
        );

    return;
}

public void function createMediumThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=300, maxWidth=300),
        getMediumImagePath(),
        0.75,
        true
        );

    return;
}

public void function createSmallThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=50, maxWidth=50),
        getSmallImagePath(),
        0.75,
        true
        );

    return;
}

public void function createMobileThumbnail(required any image) {
    ImageWrite(
        scale(image=ARGUMENTS.image, maxHeight=50, maxWidth=300),
        getMobileImagePath(),
        0.75,
        true
        );

    return;
}

public void function createProductThumbnails(required any image) {
    createLargeThumbnail(argumentCollection=ARGUMENTS);
    createMediumThumbnail(argumentCollection=ARGUMENTS);
    createSmallThumbnail(argumentCollection=ARGUMENTS);
    createMobileThumbnail(argumentCollection=ARGUMENTS);

    return;
}

createProductThumbnails(ImageReadBase64(ARGUMENTS.ImageUpload));
我需要做些什么来启动垃圾收集?
感谢你的帮助!

最佳答案

您正在拨打 scale()四次(在每个 createXXXThumbnail() 中),有效地将您的内存使用量增加了四倍,因为您明确地 duplicate()通过参数传递的图像对象。你也调用原生ImageScaleToFit() with the expensive default interpolation四次,这大概在内部创建了另一个字节数组。因此,看似无辜的 20 MB 在处理过程中很容易膨胀到 160 MB 甚至更多。

关于java - "java.lang.OutOfMemoryError: Java heap space"在 ColdFusion 11 中使用 ImageReadBase64() 读取大图像时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64882065/

相关文章:

java - 自动从构造函数中删除未使用的参数(Eclipse、Java)

opencv - 打印 cv::Mat opencv

javascript - 使用 ajax 保存 Web 应用程序的用户选择

Coldfusion 的 StructCopy 和 URL 范围

flash - Flash 中的 ColdFusion session 未定义错误

java - 碧 Jade 报告 : How to compile subreports

java - 如果 MongoDB 无法访问,如何得到错误?

java - 为构造函数创建 java native 方法

matlab - Open-CV Haar教练应用程序

image-processing - Python低对比度图像边缘检测