当前位置: 首页 > news >正文

ZSTD 内存泄漏问题

优质博文:IT-BLOG-CN

Zstandard(简称zstd)是一种无损压缩算法,由Facebook开发并开源。它旨在提供高压缩比和高解压速度的平衡,适用于多种数据压缩需求。

特点
【1】高压缩比: zstd能够在保持较高压缩比的同时,提供比其他压缩算法更快的压缩和解压速度。
【2】快速解压: 解压速度非常快,适合需要高效解压的应用场景。
【3】可调压缩级别: zstd支持多种压缩级别,从快速压缩到高压缩比,可以根据具体需求进行调整。
【4】流压缩: 支持流式压缩和解压,适合处理大文件或数据流。
【5】多线程支持: zstd支持多线程压缩,能够充分利用多核处理器的性能。

用途
【1】数据存储: 用于压缩存储在磁盘上的数据,以减少存储空间占用。
【2】数据传输: 在网络传输中使用zstd压缩数据,可以减少传输时间和带宽消耗。
【3】日志压缩: 用于压缩日志文件,减少日志存储空间。
【4】数据库: 一些数据库系统使用zstd来压缩数据页,提升存储效率。
【5】文件系统: 某些文件系统支持zstd压缩,以提高存储效率。

示例代码:以下是一个简单的Java示例,演示如何使用zstd进行压缩和解压:

import com.github.luben.zstd.Zstd;
import java.nio.charset.StandardCharsets;public class ZstdExample {public static void main(String[] args) {String originalString = "This is a string to be compressed using zstd!";byte[] originalData = originalString.getBytes(StandardCharsets.UTF_8);// 压缩数据byte[] compressedData = Zstd.compress(originalData);// 解压数据byte[] decompressedData = Zstd.decompress(compressedData, originalData.length);String decompressedString = new String(decompressedData, StandardCharsets.UTF_8);System.out.println("Original: " + originalString);System.out.println("Compressed size: " + compressedData.length);System.out.println("Decompressed: " + decompressedString);}
}

我们在使用zstd组件时发现有一个问题,容易造成内存泄露,大家如有使用或即将使用时要注意下,具体分析如下:

大家能从使用代码上看出问题来吗?看着非常正常。

try (ByteArrayInputstream byteInputstream = new ByteArrayInputstream(obj. getBytes(encoding));ByteArrayoutputstream byteOutputstream  new ByteArrayoutputstream()Zstdoutputstream zstdoutputstream = new Zstdoutputstream(byteoutputstream))(byte[] buffer . new byte[CompressConstant.DEFAULT_SIZE_512];int count;while((count= byteInputStream. read(buffer, 0CompressConstant. DEFAULT SIZE 512))1=-1){zstdoutputstream.write(buffer, , count);}zstdoutputStream.flush();zstdoutputStream.close();

Zstd原码, 重写了finalize,这就是问题根源。

package com.github.luben.zstd;
import java.io.Outputstream;
import java.io.FilterOutputStream;
import java.io. IOException;
import com.github.luben.zstd.util.Native;public class Zstdoutputstream extends Filteroutputstream(static{}/** Opaque pointer to Zstd context object */private long stream;private long srcPos - 0private long dstPos = 0private byte[] dst = null;private boolean isclosed.false;private static final int dstSize =(int) recommendedCOutSize();private boolean closeFrameonFlush;private boolean useChecksum;private boolean frameClosed . true;private int level;private byte[] dict = null;private ZstdDictCompress fastDict . null;/* JNI methods */private static native long recommendedcoutsize();private static native long createcstream();private static native int freeCStream(long ctx);private native int initCStream(long ctx, int level, int checksum);private native int initCStreamithDict(long ctx, byte[] dict, int dict_size, int level, int checksum);private native int initCStreamwithFastDict(long ctx, ZstdDictCompress dict, int checksum);private native int compressstream(long ctx, byte[] dst, int dst_size, byte[] src, int src_size);private native int flushStream(long ctx, byte[] dst, int dst_size);private native int endStream(long ctx, byte[] dst, int dst_size);/* The constuctor */public Zstdoutputstream(Outputstream outstream, int level, boolean closeFrameOnFlush, boolean useChecksum) throws IOException(}public synchronized void write(byte[] src, int offset, int len) throws IOException (}public void write(int i) throws IOException(}/***Flushes the output*/public synchronized void flush() throws IOException {}public synchronized void close() throws IOException {}@overrideprotected void finalize() throws Throwable(close();}

咱们来了解下finalize
finalizeObject对象里的一个方法,它最大的一个特点是执行时机不可预知。实现了objectfinalize方法的类,在创建时会新建一个FinalizerReference,这个对象是强引用类型,重写finallize的对象如果没有被其它对象引用时,执行GC不会马上被清除掉,而是放入到一个静态队列中,有一个守护线程专门去处理这个队列,因为守护线程的优先级比较低,运行的时间少,如果在短时间内创建较多或较大对象时,无论怎么调用GC都无用,只能等到守护线程从队列中取出finalize方法,FinalizerReference才能被回收。

Object.finalize方法是Java中定义在java.lang.Object类中的一个方法。它的主要作用是在对象被垃圾回收器回收之前进行一些清理操作。具体来说,finalize方法允许开发者在对象被销毁之前执行一些必要的清理工作,比如释放资源(文件、网络连接等)。

作用:
资源释放:在对象被垃圾回收前释放系统资源,如关闭文件、网络连接等。
清理操作:执行一些清理工作,确保对象的状态一致性。

优点
资源管理:在某些情况下,finalize方法可以用来确保资源被正确释放,避免资源泄漏。
自动调用:在垃圾回收时自动调用,无需手动触发。

缺点
不确定性:finalize方法的调用时间是不确定的,垃圾回收器何时调用finalize方法是不可预测的,这可能导致资源长时间未被释放。
性能开销:使用finalize方法会增加垃圾回收的开销,影响性能。

复杂性: finalize方法容易引入复杂的错误和难以调试的问题,因为它是在垃圾回收的过程中异步调用的。
替代方案: Java 7引入了try-with-resources语法和AutoCloseable接口,这些提供了更好的资源管理方式,通常不需要依赖finalize方法。

实际使用
由于上述缺点,finalize方法在实际开发中已经很少被使用。现代Java开发更倾向于使用try-with-resources语法和AutoCloseable接口来管理资源。例如:

try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {// 读取文件内容
} catch (IOException e) {e.printStackTrace();
}
// 这里BufferedReader会自动关闭,无需依赖finalize

看下Finalizer类的原码:

final class Finalizer extends FinalReference<Object> { 
/* Package-private; must be in
same package as the Reference
class */private static ReferenceQueue<Object> queue = new ReferenceQueue<>();private static Finalizer unfinalized = null,private static final Object lock = new Object();
private Finalizer(Object finalizee){super(finalizee, queue);add();
}
/*  Invoked by VM */
static void register(Object finalizee) { new Finalizer(finalizee); }
static {ThreadGrouptg=Thread.currentThread().getThreadGroup();for (ThreadGroup tgn = tg;tgn != null;tg = tgn, tgn = tg.getParent());Thread finalizer = new FinalizerThread(tg);___finalizer.setPriority(Thread.MAX PRIORITY - 2);finalizer.setDaemon(true);|finalizer.start();
}
private static class FinalizerThread extends Thread {private volatile boolean running;FinalizerThread(ThreadGroup g){super(g, name: "Finalizer");}public void run() {if(running)return;// Finalizer thread starts before System.initializeSystemClass// is called. Wait until JavaLangAccess is availablewhile(!VM.isBooted()){// delay until VM completes initialization try {VM.awaitBooted();} catch (InterruptedException x){// ignore and continue}}final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();running = true;for(;;){try {Finalizer f = (Finalizer)queue.remove();_f.runFinalizer(jla);} catch(InterruptedException x){// ignore and continue}
}

看下重写了finalize方法的效果,因为我们的对象比较大且请求次数多,所以发上生产就能立马见效。

Dump的结果:

在这里插入图片描述

解决方法有两个:
【1】直接用Zstdcompress(byte[] src),decompress(byte[] src, int originalSize);
【2】写一个类继承ZstdOutputStream,重载finalize,方法内置空。

大家在写代码时,尽量不要重写objectfinalize.

相关文章:

ZSTD 内存泄漏问题

优质博文&#xff1a;IT-BLOG-CN Zstandard&#xff08;简称zstd&#xff09;是一种无损压缩算法&#xff0c;由Facebook开发并开源。它旨在提供高压缩比和高解压速度的平衡&#xff0c;适用于多种数据压缩需求。 特点 【1】高压缩比&#xff1a; zstd能够在保持较高压缩比的…...

c# npoi操作excel

今天在弄使用npoi对excel表的操作&#xff0c;遇到个问题就是使用workbook通过filestream打开后&#xff0c;让后workbook.write(filestream)居然报文件流关闭了&#xff0c;无法写入&#xff0c;弄了好久都不行&#xff0c;最后通过写2个excel文件来解决&#xff0c;现在看来我…...

十二:HTTP错误响应码:理解与应对

在现代网络技术中,HTTP(超文本传输协议)是浏览器与服务器之间沟通的基础。每当我们访问网站或发送请求,HTTP会返回一个响应码,这些代码不仅可以表示成功,还可以指示各种问题。本文将以HTTP错误响应码为主题,探讨其含义、常见类型及应对措施。 1. 400 Bad Request - 请求…...

Rust学习(六):函数式编程

Rust学习&#xff08;六&#xff09;&#xff1a;函数式编程 我们在前一篇博客中已经介绍了如何通过trait和impl实现Rust的面向对象编程&#xff0c;但是Rust本身实际上并不提倡通过类来解决问题。Rust推崇的是函数式编程&#xff0c;强调将函数作为参数值或者其他函数的返回值…...

使用 Vue 和 Create-Vue 构建工程化前端项目

目录 前言1. 工程化的意义与 Vue 的生态支持2. 搭建 Vue 工程化项目2.1 环境准备2.2 使用 create-vue 创建项目2.2.1 初始化项目2.2.2 安装依赖2.2.3 本地运行 3. Vue 项目的目录结构解析4. Vue 开发流程详解4.1 项目入口与根组件4.1.1 main.js 的作用4.1.2 App.vue 的结构 4.2…...

opencv图片明暗度判断方法

OpenCV 的LAB 颜色空间&#xff08;也称为 CIELAB&#xff09;是一种颜色对手的颜色模型&#xff0c;它旨在模仿人类的色彩感知。LAB 颜色空间由三个分量组成&#xff1a; L: 亮度分量 (Lightness)&#xff0c;范围从 0&#xff08;黑色&#xff09;到 100&#xff08;白色&…...

QT6学习第三天

QT6学习第三天 第一个Widgets项目创建项目项目界面简单介绍编译文件介绍 我在第一天中将重点标了颜色&#xff0c;后边我把一些简单的东西都不写了&#xff0c;写了的都是实际用的东西&#xff0c;就不标颜色了。 第一个Widgets项目 首先我们创建一个widgets项目&#xff0c;…...

计算机网络-MSTP基础实验一(单域多实例)

前面我们已经大致了解了MSTP的基本概念和工作原理&#xff0c;但是我自己也觉得MSTP的理论很复杂不结合实验是很难搞懂的&#xff0c;今天来做一个配套的小实验以及一些配置命令。 一、网络拓扑 单域多实例拓扑 基本需求&#xff1a;SW1为VLAN10的网关&#xff0c;SW2为VLAN20的…...

React合成事件及其核心思想详解

相关联Javascript知识 1.JavaScript 的事件流 事件流是 JavaScript 处理事件的机制&#xff0c;它描述了事件从发生到被处理的过程。事件流主要包括两个阶段&#xff1a;捕获阶段和冒泡阶段。在捕获阶段&#xff0c;事件从文档的根元素开始&#xff0c;逐层向下传播到目标元素&…...

Datawhale模型减肥秘籍Tasking之模型量化

Datawhale模型减肥秘籍Tasking之模型量化 什么是量化&#xff1f;为什么量化&#xff1f;量化基本方法基于k-means的量化线性量化 训练后量化量化粒度动态量化参数的计算 ( Cliping )指数移动平均&#xff08;EMA&#xff09;Min-MaxKL 量化均方误差&#xff08;MSE&#xff09…...

在云服务器搭建 Docker

操作场景 本文档介绍如何在腾讯云云服务器上搭建和使用 Docker。本文适用于熟悉 Linux 操作系统&#xff0c;刚开始使用腾讯云云服务器的开发者。如需了解更多关于 Docker 相关信息&#xff0c;请参见 Docker 官方。 说明&#xff1a; Windows Subsystem for Linux&#xff…...

Redis 的代理类注入失败,连不上 redis

在测试 redis 是否成功连接时&#xff0c;发现 bean 没有被创建成功&#xff0c;导致报错 根据报错提示&#xff0c;需要我们添加依赖&#xff1a; <dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId>&l…...

版本控制【Git Bash】【Gitee】

目录 一、什么是版本控制&#xff1f; 二、版本控制的种类&#xff1a; 1、本地版本控制 2、集中版本控制 3、分布式版本控制 三、下载Git Bash 四、Git Bash 配置 五、Git Bash使用 1、切换目录&#xff1a;cd 2.查看当前文件路径&#xff1a;pwd 3.列出当前目录下文件…...

Neo4j Desktop 和 Neo4j Community Edition 区别

Neo4j Desktop 和 Neo4j Community Edition 的主要区别在于它们的用途、功能以及安装和管理方式。以下是这两者的详细对比&#xff1a; 1. Neo4j Desktop Neo4j Desktop 是一个图形化的桌面应用程序&#xff0c;主要为开发人员和个人使用提供了一个便捷的环境来安装、管理和运…...

使用uniapp开发微信小程序使用uni_modules导致主包文件过大,无法发布的解决方法

在使用uniapp开发微信小程序时候&#xff0c;过多的引入uni_modules的组件库&#xff0c;会导致主包文件过大&#xff0c;导致无法上传微信小程序&#xff0c;主包要求大小不超过1.5MB.分包大小每个不能超过2M。 解决方法&#xff1a;分包。 1.对每个除了主页面navbar的页面进…...

HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)事件推荐开发者测试

意图框架向开发者提供真机测试能力&#xff0c;即开发者可连接设备进行调测。开发者完成代码开发之后&#xff0c;功能正式上架应用市场前&#xff0c;可以在HarmonyOS NEXT设备上面进行自验证&#xff0c;打磨体验。真机测试分为三个步骤&#xff1a;基础信息提供&#xff0c;…...

GD32F103 实践-- MCU编译运行

编译 打开固件库示例工程&#xff1a;在SDK路径下找到固件库示例工程&#xff0c;路径通常是SDK\GD32F10x_Firmware_Library_Template\Keil5_project\Project 选择芯片型号&#xff1a;根据你的MCU型号选择&#xff0c;例如GD32F103RCT6 修改宏定义&#xff1a;根据MCU型号修…...

SQL复杂数据类型处理

背景 数据处理中&#xff0c;经常碰到复杂数据类型&#xff0c;需要将他们进行解析才能利用。 复杂数据类型 1、MAP结构转为列 WITH tmp AS ( SELECT {"Users":{"4418":{"UserId":4418,"Score":0,"IsStudent":true},&q…...

ROS第九梯:ROS+VSCode+Python+C++自定义消息发布和订阅

首先,Python版本的ROS项目和C++版本的ROS项目前期创建功能包的步骤基本一致,具体可参考第二章。 费一步:新建msg文件 在功能包(data_input)目录下创建一个msg文件夹,并在msg文件夹下创建一个名为Box的msg文件,具体如下图所示: 该msg文件为一个用于描述3D Box的文件,…...

【Linux】指令 + 压缩与解压

Linux 一.Linux基本指令1.grep2.zip和unzip1.Linux中的压缩文件发送Windows中2.Linux中接收Windows中压缩文件 3.tar&#xff08;重要&#xff09;1.Linux与Linux互传压缩文件 4.bc5.uname 二.Linux相关知识点1.Linux常用热键2.关机操作 一.Linux基本指令 1.grep 行文本过滤工…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...