【问题标题】:Out of memory when I create a json object based in json array当我创建基于 json 数组的 json 对象时内存不足
【发布时间】:2013-02-10 18:57:12
【问题描述】:

我在 java 中创建了一个 web 服务来返回 json 数据。好的,小数据没问题,但是当我处理大数据时,它会返回内存不足的错误。

查看我的代码:

public void getImages() throws Exception {
      JSONObject o = new JSONObject();
      JSONArray jsonArray = new JSONArray();

      try {
                Class.forName(DRIVERNAME);
                conn = DriverManager.getConnection(URL, USER, PASS);

                Statement s = connection.createStatement();
                ResultSet r = s.executeQuery("select * from images");

                while (r.next()) {
                          JSONObject obj = new JSONObject();

                          obj.put("id", r.getInt("id"));

                          byte[] iBytes = r.getBytes("image");
                          String iBase64 = DatatypeConverter.printBase64Binary(iBytes);
                          obj.put("image", iBase64);

                          jsonArray.put(obj);
                }

                o.put("images", jsonArray);

      } catch (SQLException e) {

      }
}

在 jsonArray 中添加图像时发生内存不足 (java.lang.OutOfMemoryError: Java heap space):

byte[] iBytes = r.getBytes("image");
String iBase64 = DatatypeConverter.printBase64Binary(iBytes);
obj.put("image", iBase64);

知道如何解决这个问题吗?

【问题讨论】:

  • 要么不这样做,要么增加可用内存量。
  • 您通常在一次通话中检索多少张图片,它们有多大?您当前的代码非常占用内存,如果您遇到 OOM 问题,那么您将需要增加程序可用的内存量,或改进逻辑以减少您尝试发送回客户端的数据量。
  • 您确定要通过 json 传输图像字节数据吗?如果你真的想这样做,也许你可以设置图像大小的限制或调整它们的大小。
  • @Perception 该调用平均返回 2000 张图像。我需要将图像存储在应用程序移动设备上以供离线工作。所以,我不知道分页结果以避免内存不足。那么,有什么想法吗?
  • 两千?这对于任何类型的应用程序来说都很多,更不用说移动应用程序了。您将遇到双方的内存问题。根据平均图像大小(您没有提到),您肯定需要对结果集进行分页。

标签: java json web-services tomcat out-of-memory


【解决方案1】:

使用来自 Jackson Library 的流 json(ObjectMapper、JsonFactory、JsonGenerator)解决您的问题。请看下面的代码:

public void getImages() throws Exception {

    ObjectMapper objectMapper = new ObjectMapper();
    JsonFactory jf = objectMapper.getFactory();
    JsonGenerator jg = f.createGenerator(new File("c:\\images.json"), JsonEncoding.UTF8);

    try {
        Class.forName(DRIVERNAME);
        conn = DriverManager.getConnection(URL, USER, PASS);

        Statement s = connection.createStatement();
        ResultSet r = s.executeQuery("select * from images");

        jg.writeFieldName("images");
        jg.writeStartArray();

        while (r.next()) {
           jg.writeBinary(r.getBinaryStream("IMAGEM"), -1);
           in.close();
        }

        jg.writeEndArray(); 
        jg.writeEndObject(); 
        jg.close();

    } catch (SQLException e) {
        //use the exceptions
    }
}

【讨论】:

  • 你这里的“in”变量是什么......你也忘了 writeStartObject()。
【解决方案2】:

您为什么不简单地将 url 返回到图像并让浏览器拉取该资源?我不太明白通过您的 json 响应传递它的优势,因为您要求 java 在发送之前将图像集保存在内存中。

【讨论】:

  • 我不能这样做,因为移动应用程序将离线工作。因此,用户移动应用程序不会访问互联网来请求 url。
  • 在这种情况下,您需要将堆大小配置为更大
  • 我评论了创建图像和内存不足问题的行。
猜你喜欢
  • 2019-01-26
  • 1970-01-01
  • 2016-05-30
  • 2018-07-03
  • 2017-09-27
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多