使用stream下载文件避坑-》堆内存溢出的原因

2023-11-11

场景

。下载80MB的文zip文件正常,大文件就下载不下来,下载为0KB

原因

下载大文件耗时间,设置了超时时间,其实文件没有下载下来
conn.setConnectTimeout(3 * 1000);

并不是上面那个原因

这段代码表示通过 HttpURLConnection 建立HTTP连接,并设置连接的超时时间为3秒。具体而言, setConnectTimeout() 方法设置了建立连接的超时时间,即在连接建立过程中,如果服务器在3秒内没有响应,连接将会超时。超时后,会抛出 java.net.SocketTimeoutException 异常。这个超时时间通常需要根据网络质量和服务器响应时间调整,如果连接建立时间比较长,可以适当增加超时时间,避免网络等待时间过长。

解决

后端给出下载地址,前端下载

过程

刚开始以为文件没有上传上来,发现数据库中已经上传了。后来又想到了文件的头
添加链接描述

解决

这个问题出现的原因是Java堆空间不足,可能是因为下载的大文件导致内存占用过高,建议使用 InputStreamOutputStream 的方式进行下载,可以将下载过程分为多次读写,这样可以避免一次性读取整个文件内容导致内存占用过高。
具体而言,可以使用如下代码进行下载:

这个代码通过 HttpURLConnection 打开文件连接,然后使用 InputStream 读取文件内容,将文件内容写入到 OutputStream 中,将文件存储在本地磁盘上。使用这种方式可以有效避免一次性读取整个文件内容导致内存占用过高的问题。
另外,还可以考虑优化Java堆空间的分配,例如通过调整JVM启动参数设置Java堆空间的最小值和最大值,或者使用内存压缩算法等机制来减小内存占用。

URL url = new URL(fileUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try (InputStream inputStream = conn.getInputStream();
     OutputStream outputStream = new FileOutputStream(localFilePath)) {
    byte[] buffer = new byte[4096];
    int bytesRead = -1;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
    }
}

实际原因

全局异常信息 ex=Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space

Java程序在运行过程中会产生多种对象,这些对象需要存储在Java堆中,Java堆作为Java虚拟机管理的一块内存空间,是Java程序运行所必须的。如果Java堆中的对象太多,内存无法满足程序的需求,就会出现Java堆内存溢出(OOM)的情况。
Java程序中出现堆内存溢出的原因主要有以下几点:

  1. 内存泄漏导致对象无法被垃圾回收器回收。例如,程序中持有大量未使用的对象引用,或者未关闭的数据库连接、IO流等资源。
  2. 某些对象太大,占用了大量的Java堆空间,导致Java堆空间不足,无法为新的对象分配足够的内存空间。
  3. 程序中存在大量临时对象,内存分配不当导致内存碎片严重,无法为大对象分配连续的内存空间。
  4. 程序中使用递归操作,导致方法调用栈的深度过大,占用大量的Java堆空间。
    当发生Java堆内存溢出时,程序会抛出 java.lang.OutOfMemoryError 异常,这个异常不能被程序捕获,只能被Java虚拟机捕获,它表示Java堆内存已经满了,无法再为新的对象分配内存空间。为了避免Java堆内存溢出,需要进行合理的内存管理和优化,例如使用缓存技术、调整堆内存大小等方式。
    添加链接描述

堆内存

堆内存溢出的原因

Java程序在运行过程中会产生多种对象,这些对象需要存储在Java堆中,Java堆作为Java虚拟机管理的一块内存空间,是Java程序运行所必须的。如果Java堆中的对象太多,内存无法满足程序的需求,就会出现Java堆内存溢出(OOM)的情况。
Java程序中出现堆内存溢出的原因主要有以下几点:

  1. 内存泄漏导致对象无法被垃圾回收器回收。例如,程序中持有大量未使用的对象引用,或者未关闭的数据库连接、IO流等资源。
  2. 某些对象太大,占用了大量的Java堆空间,导致Java堆空间不足,无法为新的对象分配足够的内存空间。
  3. 程序中存在大量临时对象,内存分配不当导致内存碎片严重,无法为大对象分配连续的内存空间。
  4. 程序中使用递归操作,导致方法调用栈的深度过大,占用大量的Java堆空间。
    当发生Java堆内存溢出时,程序会抛出 java.lang.OutOfMemoryError 异常,这个异常不能被程序捕获,只能被Java虚拟机捕获,它表示Java堆内存已经满了,无法再为新的对象分配内存空间。为了避免Java堆内存溢出,需要进行合理的内存管理和优化,例如使用缓存技术、调整堆内存大小等方式。

什么情况下会占用堆内存

在Java程序运行过程中,所有的对象和数组都是在堆内存上分配的,所以Java程序需要占用堆内存来存储所有的对象和数组。以下是一些可能会占用堆内存的情况:

  1. 创建对象:每当使用 new 关键字创建一个对象时,一个新的对象就会被分配到堆内存中。
  2. 创建数组:类似于对象,Java数组也是在堆内存中分配的。
  3. 方法调用:每当调用一个方法时,为该方法创建的局部变量和参数都会在堆内存中分配空间。
  4. 递归调用:递归是一种特殊的方法调用,会在堆内存中创建多个方法调用栈。
  5. 缓存对象:如果程序中缓存了大量的对象,那么这些对象也会占用堆内存。
  6. 长生命周期的对象:有些对象的生命周期比较长,比如单例模式中的对象,这些对象也会占用堆内存。
  7. 引用对象:如果程序中有多个对象相互引用,那么这些对象也会占用堆内存。
    总之,任何在Java程序中创建、存储或引用对象和数组的操作都会占用堆内存。因此,Java程序的堆内存大小和堆内存使用情况对程序的性能和稳定性都有重要影响。

一个微服务堆内存设置为多大

在Java程序运行过程中,所有的对象和数组都是在堆内存上分配的,所以Java程序需要占用堆内存来存储所有的对象和数组。以下是一些可能会占用堆内存的情况:

  1. 创建对象:每当使用 new 关键字创建一个对象时,一个新的对象就会被分配到堆内存中。
  2. 创建数组:类似于对象,Java数组也是在堆内存中分配的。
  3. 方法调用:每当调用一个方法时,为该方法创建的局部变量和参数都会在堆内存中分配空间。
  4. 递归调用:递归是一种特殊的方法调用,会在堆内存中创建多个方法调用栈。
  5. 缓存对象:如果程序中缓存了大量的对象,那么这些对象也会占用堆内存。
  6. 长生命周期的对象:有些对象的生命周期比较长,比如单例模式中的对象,这些对象也会占用堆内存。
  7. 引用对象:如果程序中有多个对象相互引用,那么这些对象也会占用堆内存。
    总之,任何在Java程序中创建、存储或引用对象和数组的操作都会占用堆内存。因此,Java程序的堆内存大小和堆内存使用情况对程序的性能和稳定性都有重要影响。

堆内存什么时候会被回收以及回收的原理

Java中的垃圾回收器会定期扫描堆内存,检查哪些对象没有被引用(GC Roots)而无法访问,然后将这些对象回收并释放它们所占用的内存。垃圾回收器使用标记-清除算法或标记-整理算法来回收堆内存中的无用对象。
垃圾回收的过程分为以下几个步骤:

  1. 标记阶段:垃圾回收器会遍历堆内存,标记所有被引用的对象,标记完成后,所有未被标记的对象即为无用对象。
  2. 清除阶段:垃圾回收器会清除所有未被标记的对象,并释放它们占用的内存。
  3. 整理阶段(可选):如果使用标记-整理算法,回收器会压缩堆内存,将存活的对象移到一块连续的空间,这样可以优化堆内存的空间使用。
    需要注意的是,Java垃圾回收器是一个自动化的过程,程序员不需要手动释放内存。通常情况下,垃圾回收器会优先回收那些占用空间最大的对象,以便尽快释放内存。
    有一点需要注意的是,如果程序中存在内存泄漏或者对象引用没有正确处理,堆内存中的对象就会变得越来越多,垃圾回收器处理的时间也会变得越来越长,甚至会导致OutOfMemoryError的异常。因此,编写Java程序时,必须要注意及时释放不再需要的对象,以避免内存泄漏等问题。

解决内存泄漏的根本方法,最好的做法是在程序中尽可能减少无用对象的产生,避免堆内存的不必要浪费。

堆内存溢出通常是因为程序中创建了大量的对象,而这些对象占用的内存超过了堆内存的容量。为避免堆内存溢出,可以采用以下几种方法:

  1. 尽量少创建不必要的对象。在Java程序中,通过new操作符创建对象时,会在堆内存中分配内存空间,因此尽量避免创建不必要的对象,特别是在循环中创建对象的情况。
  2. 调整JVM的堆内存大小。可以在启动Java程序时,通过指定-Xmx和-Xms参数来控制Java虚拟机的堆内存大小,以适应不同的应用场景。
  3. 及时释放不再使用的对象。当不再需要使用一个对象时,应该及时将它的引用设置为null,这样垃圾回收器会将这个对象标记为无用对象。程序中如果有一些很大的对象只使用了一次,也应该及时释放。
  4. 对于使用集合类的代码,应该尽量使用Iterator而不是for-each循环,因为for-each循环会在每次循环中创建一个Iterator对象,占用额外的内存空间。
  5. 使用对象池或缓存池。对于一些需要频繁创建和销毁的对象,可以使用对象池或缓存池来重复利用对象,减少创建和销毁对象的次数。
  6. 使用大对象时应该注意。一般来说,大对象的创建和销毁会占用大量的堆内存,因此在使用大对象时应该特别注意,尽量减少大对象的创建和销毁次数。
    总之,避免堆内存溢出需要从多个方面入手,对代码进行优化和改进。

这个错误通常是由于Java程序占用的内存超过了堆内存的容量而导致的。为解决这个问题,可以采用以下几种方法:

  1. 调整JVM的堆内存大小。可以通过指定-Xmx和-Xms参数来增大堆内存的容量。例如,可以将-Xmx和-Xms参数设置为2G,即2GB,来增大堆内存的容量。具体操作方法可以参考实际使用的容器或JVM的文档。
  2. 优化代码,减少内存占用。可以通过减少创建对象、及时释放对象等方式来减少内存的占用。具体操作方法可以根据代码情况进行优化。
    3. 使用内存分析工具,查找内存泄漏。内存泄漏指的是程序中仍然持有对象的引用,而这些对象已经不再使用。可以使用内存分析工具来查找内存泄漏问题,并及时修复。
    总之,解决这个问题需要从多个方面入手,对代码进行优化和改进,并适当调整JVM的堆内存大小。
    使用内存分析工具进行分析,可以从以下几个方面入手:
  3. 监控Java程序的内存占用情况。使用内存分析工具可以实时监控Java程序的内存占用情况,包括堆内存、非堆内存、线程、类和对象等。
  4. 查找内存泄漏。内存泄漏指的是程序中仍然持有对象的引用,而这些对象已经不再使用。使用内存分析工具可以查找内存泄漏问题,并定位引起内存泄漏的代码位置。
  5. 分析对象的使用情况。使用内存分析工具可以分析对象的使用情况,包括对象的个数、大小、创建和销毁时间等,从而可以找出一些不必要的对象创建和销毁操作,优化程序性能。
  6. 分析线程的使用情况。使用内存分析工具可以分析线程的使用情况,包括线程的状态、数量、调用堆栈等,从而可以找出一些线程阻塞或死锁的问题,提高程序的并发性能。
  7. 分析类的加载情况。使用内存分析工具可以分析类的加载情况,包括类的数量、大小、是否被缓存等,从而可以找出一些不必要的类加载操作,优化程序启动性能。
    在使用内存分析工具进行分析时,可以使用一些常用的工具,如Eclipse Memory Analyzer Tool、VisualVM等。具体使用方法可以参考相关工具的官方文档或使用指南。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用stream下载文件避坑-》堆内存溢出的原因 的相关文章

随机推荐

  • 密码学基础系列之(2.1传统对称密钥密码之三)

    多码代换密码 多码代换中 明文字符与密文字符的关系是一对多 密文C除了与明文P有关外 还与P的位置有关 自动密钥密码 autokey cipher P P1P2P3 C C1C2C3 k k1 P1 P2 加密 Ci Pi ki mod N
  • c语言 adt实验报告,Android实验报告

    Android实验报告 由会员分享 可在线阅读 更多相关 Android实验报告 90页珍藏版 请在人人文库网上搜索 1 Android 实验报告 专业 计算机科学与技术 班级 13419011 学号 1341901124 姓名 武易 精品
  • 已经上架的app(可供销售)在AppStore上搜不到的解决办法

    能搜索到但是是旧版本的情况 把你的app价格调为6元RMB 然后地区只选择中国 保存 这样你的app状态就会变成pending contract 然后把你的app调整成免费 地区全选 保存 再等半小时左右 AppStore就可以搜到了 亲测
  • 【机器学习项目实战】Python基于协同过滤算法进行电子商务网站用户行为分析及服务智能推荐

    说明 这是一个机器学习实战项目 附带数据 代码 文档 代码讲解 如需数据 代码 文档 代码讲解可以直接到文章最后获取 1 项目背景 电子商务网站数量迅速上升 将电子商务网站浏览者变为实际消费者 满足消费者需求 通过不同形式提升消费者忠诚度是
  • 兼容性测试方案

    目的 快速覆盖用户的各种操作环境 进行快速验证 1 常规项目测试策略 提高重视度 在需求分析 测试设计 测试执行 收尾阶段都要加大兼容性测试的比重 1 1 需求阶段 在需求阶段要获取兼容性测试环境的来源 来源为产品经理和用户现场使用情况 更
  • java动态规划,求最大子段和,并且求出开始位置,结束位置

    public static void main String args int x 1 3 2 11 8 4 13 5 4 8 5 System out println 最大子段和为 MaxAdd x private static int
  • 基础设计一——FPGA学习笔记<2>

    目录 零 设计流程 一 按键点亮LED灯 1 硬件资源 2 项目设计 3 波形设计 4 创建Vivado工程 编辑 lt 1 gt 添加设计文件 lt 2 gt 添加仿真文件 5 引脚约束 6 生成比特流文件 7 下载验证 8 程序固化 二
  • for-loop 与 json.Unmarshal 性能分析概要

    原文地址 for loop 与 json Unmarshal 性能分析概要 前言 在项目中 常常会遇到循环交换赋值的数据处理场景 尤其是 RPC 数据交互格式要转为 Protobuf 赋值是无法避免的 一般会有如下几种做法 for for
  • Spring入门概述及基本知识点

    Spring是什么 我们常说的Spring 其实在官网中全称是SpringFrameWork Spring是一个轻量级 非入侵式的Java开发框架 主要用于业务层 和整合其他层 解决了业务层和表现层 持久层的耦合问题 将面向接口编程贯穿整个
  • boost介绍

    boost是一个准标准库 相当于STL的延续和扩充 它的设计理念和STL比较接近 都是利用泛型让复用达到最大化 不过对比STL boost更加实用 STL集中在算法部分 而boost包含了不少工具类 可以完成比较具体的工作 boost主要包
  • CVPR21 - BasicVSR:简单有效的视频超分辨率Baseline

    文章目录 原文信息 初识 相知 组件分析 BasicVSR IconVSR 部分实验 回顾 原文信息 原文链接 初识 相比于图像超分 视频超分 VSR Video Super Resolution 显然是一件更具挑战性的任务 视频超分比图像
  • Two slices reporting being the first in the same frame. 和 Could not find ref with POCXX问题

    hevc 000001716438fc00 Two slices reporting being the first in the same frame hevc 000001716439ec80 Could not find ref wi
  • 黑马并发编程(AQS源码分析、线程池)

    AQS源码分析 线程池 8 线程池 1 自定义线程池 阻塞队列 优化队列 线程池 执行和线程处理设计 线程池执行的整个思路 阻塞添加 拒绝策略 2 ThreadExecutor 线程池状态 线程池参数 拒绝策略 newFixedThread
  • 本地上传文件到Linux服务器

    问题描述 如何将本地文件上传至Linux服务器上 这里分别以Windows和Ubuntu系统为例 解决方法 scp filename username IP home directory 举个例子 scp data zip zhangsan
  • 打造利器Qt Creator:代码todo工具的使用

    打造利器Qt Creator 代码todo工具的使用 前言 俗话说 工欲善其事必先利其器 工作生活中 能有一款出色易用 高效简便的工具 对提高效率 达成价值有着莫大的影响 Qt是一套C 库 封装了许多好用的模块和功能 且带有先进的GUI设计
  • 【VUE】vue报错“‘vue-cli-service‘不是内部或外部命令,也不是...”的解决办法

    问题描述 项目执行npm run serve后报错 产生原因 最大概率原因 由于在该代码中含有node module依赖包 再拷贝到其他计算机时 项目路径发生变化 导致找不到vue cli service于是报错 其他出错情况 见下文扩展
  • 如何更好的利用区块链API

    区块链允许数据提供者和消费者直接在单个开放系统中交易信息 而不是订阅世界各地的数十个集中服务 并编写他们的软件来与每个API进行通信 阅读此区块链API教程 了解如何根据你的特定需求使用它 API 应用程序编程接口 是单个计算机程序可以用来
  • synchronized和ReentrantLock的比较

    六 synchronized和ReentrantLock的比较 1 区别 1 Lock是一个接口 而synchronized是Java中的关键字 synchronized是内置的语言实现 2 synchronized在发生异常时 会自动释放
  • IDEA 的 maven项目 Plugins以及Dependencies 爆红 红波浪线

    IntelliJ idea新建Maven项目 Plugins以及Dependencies下有红色波浪线 如图 一 配置maven的Local repository 点击File gt Settings gt Build Execution
  • 使用stream下载文件避坑-》堆内存溢出的原因

    场景 下载80MB的文zip文件正常 大文件就下载不下来 下载为0KB 原因 下载大文件耗时间 设置了超时时间 其实文件没有下载下来 conn setConnectTimeout 3 1000 并不是上面那个原因 这段代码表示通过 Http