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

池化技术、Commons Pool介绍

概述

池化技术,一种通过重复利用对象实例而非频繁创建和销毁的技术。

常见的可池化对象:

  • 数据库连接(Connection):数据库连接创建和销毁代价高,连接池广泛用于管理JDBC连接;
  • 线程(Thread):线程的创建和销毁开销大,线程池是多线程编程中常用的技术;
  • 网络连接(Socket/HTTPClient):复用HTTP连接以提高网络通信效率;
  • 对象实例(Object):对于短生命周期且频繁使用的对象,可通过对象池管理其生命周期;
  • 内存块或缓冲区(Buffer):I/O操作中经常使用缓冲池(如Netty的ByteBuf池)来减少内存分配和垃圾回收的开销;
  • 会话或上下文对象(Session/Context):在Web应用或分布式系统中,Session对象可通过池化优化访问性能。

具体的池化技术:

  • 数据库连接池:如HikariCP、Druid、C3P0;管理JDBC连接生命周期,包括创建、复用和回收。
  • 线程池:如Java中的ExecutorService和ThreadPoolExecutor。控制线程的并发量和资源使用,避免频繁创建线程。
  • HTTP连接池:如OkHttp、Apache HttpClient。复用HTTP连接,减少TCP连接开销。
  • 对象池:如Apache Commons Pool、HikariCP的对象池管理。用于频繁创建和销毁的轻量级对象实例。
  • 缓冲区池:如Netty的内存池(ByteBufAllocator),池化I/O缓冲区以减少垃圾回收的负担。
  • GPU内存池:如CUDA的内存池,在深度学习或图像处理场景中复用显存资源。
  • 分布式对象池:如Redisson对Redis资源的池化封装,管理分布式系统中的共享资源。

当遇到以下场景,可考虑使用池化技术来提高系统性能:

  • 对象的创建或销毁很频繁,需要使用较多的系统资源,如数据库连接、线程、HTTP请求;
  • 生命周期较短且重复使用的对象,如临时计算对象、缓冲区;
  • 需要高并发和低延迟,如Web服务、实时数据流处理;
  • 资源昂贵的操作,如GPU显存管理、大型文件处理。

优势

  • 减少资源开销:通过复用降低对象的创建和销毁成本;
  • 提高性能:更快的响应时间和更少的垃圾回收;
  • 降低复杂度:池化工具通常内置优化策略(如负载均衡、超时管理)。

注意事项

  • 资源竞争:池的大小配置过小可能导致资源争抢,过大则浪费资源;
  • 池中对象管理:需要避免对象泄漏或资源未正确释放;
  • 过期资源处理:池化资源可能因为网络或连接原因失效,需实现健康检查和自动回收。

线程池

参考面试必备之线程池(Java),以及ForkJoinPool,以及MySQL线程池。

连接池

参考JDBC与数据库连接池。

缓冲池

MySQL提供缓冲池能力,待学习。

对象池

提到对象池,不得不说ApacheGitHub的Commons Pool。

官方文档

核心组件(API):

  • 对象池(ObjectPool):实现对对象存取和状态管理的池实现,如:线程池、数据库连接池;
  • 池化对象(PooledObject):池化对象,放在ObjectPool里的包装类。添加一些附加信息,如状态,创建时间,激活时间,关闭时间等;
  • 池化对象工厂(PooledObjectFactory):工厂类,负责具体对象的创建、初始化、销毁和状态验证。

关系图
在这里插入图片描述

实战

引入如下依赖:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.12.0</version>
</dependency>

实现一个简单的数据库连接池:

@AllArgsConstructor
public class DatabaseConnectionFactory extends BasePooledObjectFactory<Connection> {private String connectionString;private String username;private String password;// 创建新的数据库连接@Overridepublic Connection create() {try {return DriverManager.getConnection(connectionString, username, password);} catch (SQLException e) {throw new RuntimeException("创建数据库连接失败", e);}}// 销毁数据库连接@Overridepublic void destroyObject(PooledObject<Connection> p) throws Exception {p.getObject().close();}// 验证数据库连接是否有效@Overridepublic boolean validateObject(PooledObject<Connection> p) {try {return p.getObject().isValid(1); // 设置一个非常短的超时,仅用于检查连接是否仍然可用} catch (SQLException e) {return false;}}// 激活对象,可选,No-op@Overridepublic void activateObject(PooledObject<Connection> p) throws Exception {// 可在这里进行一些连接重新激活的操作,例如设置自动提交、隔离级别等}// 钝化对象,可选,No-op@Overridepublic void passivateObject(PooledObject<Connection> p) throws Exception {// 可在对象返回到池之前执行一些清理或重置操作}
}

配置和创建ObjectPool:

public class DatabaseConnectionPool {private static GenericObjectPool<Connection> pool;static {// 配置连接池的参数GenericObjectPoolConfig config = new GenericObjectPoolConfig();config.setMaxTotal(10); // 设置连接池的最大连接数config.setMaxIdle(5); // 设置连接池的最大空闲连接数config.setMinIdle(2); // 设置连接池的最小空闲连接数DatabaseConnectionFactory factory = new DatabaseConnectionFactory("jdbc:mysql://localhost:3306/mydatabase", "user", "password");// 初始化连接池pool = new GenericObjectPool<>(factory, config);}// 获取数据库连接public static Connection getConnection() throws Exception {return pool.borrowObject();}// 归还数据库连接到池public static void releaseConnection(Connection conn) {if (conn != null) {pool.returnObject(conn);}}// 关闭连接池(通常在应用程序关闭时调用)public static void close() {if (pool != null) {pool.close();}}
}

最后是测试类:

public static void main(String[] args) {try (Connection conn = DatabaseConnectionPool.getConnection()) {// 使用连接执行数据库操作        // 连接会在try-with-resources块结束时自动归还到池中} catch (Exception e) {// log}// 注意:在应用程序结束时,应该调用DatabaseConnectionPool.close()来关闭连接池
}

原理

大致如下图
在这里插入图片描述
注:

  • minEvictableldleTimeMillis是早期版本的拼写,最新版2.12.0对应的参数是minEvictableIdleDuration;
  • softMinEvictableldleTimeMillis对应的参数是softMinEvictableIdleDuration;
  • timeBetweenEvictionRunsMillis对应的参数是durationBetweenEvictionRuns。

4个test参数:

  • testOnCreate:指定在创建时,是否对池化对象进行有效性检测;以下类似
  • testOnBorrow:获取
  • testOnReturn:归还
  • testWhileIdle:空闲检测

生产环境,建议只将testWhileIdle设置为true,其他几个参数设置为false,并通过调整空闲检测时间间隔(timeBetweenEvictionRunsMillis,durationBetweenEvictionRuns)来保证资源的可用性和效率。

源码

ObjectPool:

public interface ObjectPool<T> extends Closeable {// 添加对象void addObject() throws Exception;// 添加多个对象default void addObjects(final int count) throws Exception {for (int i = 0; i < count; i++) {addObject();}}// 从池中获取对象T borrowObject() throws Exception;// 清除池,池可用void clear() throws Exception;// 关闭池,池不可用@Overridevoid close();// 获取活跃对象个数int getNumActive();// 获取空闲对象个数int getNumIdle();// 废弃对象void invalidateObject(T obj) throws Exception;// 使用指定的废弃模式废弃对象default void invalidateObject(final T obj, final DestroyMode destroyMode) throws Exception {invalidateObject(obj);}// 将对象放回池中void returnObject(T obj) throws Exception;
}

枚举类DestroyMode源码如下:

public enum DestroyMode {// 常规废弃NORMAL,// Destroy abandoned objectABANDONED
}

PooledObject:

public interface PooledObject<T> extends Comparable<PooledObject<T>> {static boolean isNull(final PooledObject<?> pooledObject) {return pooledObject == null || pooledObject.getObject() == null;}boolean allocate();boolean deallocate();boolean endEvictionTest(Deque<PooledObject<T>> idleQueue);default Duration getActiveDuration() {// Take copies to avoid threading issuesfinal Instant lastReturnInstant = getLastReturnInstant();final Instant lastBorrowInstant = getLastBorrowInstant();// @formatter:offreturn lastReturnInstant.isAfter(lastBorrowInstant) ?Duration.between(lastBorrowInstant, lastReturnInstant) :Duration.between(lastBorrowInstant, Instant.now());// @formatter:on}@Deprecateddefault Duration getActiveTime() {return getActiveDuration();}@Deprecatedlong getActiveTimeMillis();default long getBorrowedCount() {return -1;}default Instant getCreateInstant() {return Instant.ofEpochMilli(getCreateTime());}@Deprecatedlong getCreateTime();default Duration getFullDuration() {return Duration.between(getCreateInstant(), Instant.now());}default Duration getIdleDuration() {return Duration.ofMillis(getIdleTimeMillis());}@Deprecateddefault Duration getIdleTime() {return Duration.ofMillis(getIdleTimeMillis());}@Deprecatedlong getIdleTimeMillis();default Instant getLastBorrowInstant() {return Instant.ofEpochMilli(getLastBorrowTime());}@Deprecatedlong getLastBorrowTime();default Instant getLastReturnInstant() {return Instant.ofEpochMilli(getLastReturnTime());}@Deprecatedlong getLastReturnTime();default Instant getLastUsedInstant() {return Instant.ofEpochMilli(getLastUsedTime());}@Deprecatedlong getLastUsedTime();T getObject();PooledObjectState getState();void invalidate();void markAbandoned();void markReturning();void printStackTrace(PrintWriter writer);void setLogAbandoned(boolean logAbandoned);default void setRequireFullStackTrace(final boolean requireFullStackTrace) {// noop}boolean startEvictionTest();void use();@Overrideint compareTo(PooledObject<T> other);@Overrideboolean equals(Object obj);	@Overrideint hashCode();String toString();
}

PooledObjectFactory,泛型接口:

public interface PooledObjectFactory<T> {void activateObject(PooledObject<T> p) throws Exception;void destroyObject(PooledObject<T> p) throws Exception;default void destroyObject(final PooledObject<T> p, final DestroyMode destroyMode) throws Exception {destroyObject(p);}PooledObject<T> makeObject() throws Exception;void passivateObject(PooledObject<T> p) throws Exception;boolean validateObject(PooledObject<T> p);
}

解读:

  • makeObject:创建一个新对象;当对象池中的对象个数不足(个数配置,参考下面的Config)时,将会使用此方法来产生一个新的对象,并交付给对象池管理;
  • destroyObject:销毁对象,如果检测到对象池中某个对象idle的时间超时,或操作者向对象池归还对象时检测到对象已经无效,则触发对象销毁。调用此方法时,对象的生命周期必须结束。如果object是线程,则线程必须退出;如果是Socket操作,则Socket必须关闭;如果是文件流操作,则此时数据flush且正常关闭。
  • validateObject:检测对象是否有效;Pool中不能保存无效的对象,因此后台检测线程会周期性的检测Pool中对象的有效性,如果对象无效则会导致此对象从Pool中移除,并destroy;此外在调用者从Pool获取一个对象时,也会检测对象的有效性,确保不会将无效的对象输出给调用者;当调用者使用完毕将对象归还到Pool时,仍然会检测对象的有效性。有效性,就是此对象的状态是否符合预期,调用者是否可直接使用;如果对象是Socket,有效性则意味着Socket的通道是否畅通/阻塞是否超时等。
  • activateObject:激活对象,当Pool中决定移除一个对象交付给调用者时额外的激活操作,比如可在activateObject方法中重置参数列表让调用者使用时感觉像一个新创建的对象一样。如果object是线程,可在激活操作中重置线程中断标记,或让线程从阻塞中唤醒等;如果是Socket,则可在激活操作中刷新通道,或对Socket进行连接重建(假如Socket意外关闭)等。
  • passivateObject:钝化对象,当调用者归还对象时,Pool将会钝化对象。如果object是Socket,则清除buffer,将Socket阻塞;如果是线程,可在钝化操作中将线程sleep或将线程中的某个对象wait。activateObject和passivateObject两个方法需要一一对应,避免死锁或对象状态的混乱。

BaseObjectPoolConfig提供的配置:

  • lifo:连接池放池化对象方式,默认为true
  • true:放在空闲队列最前面
  • false:放在空闲队列最后面
  • fairness:等待线程拿空闲连接的方式,默认为false
  • true:相当于等待线程是在先进先出去拿空闲连接
  • maxWaitMillis:当连接池资源耗尽时,调用者最大阻塞的时间,超时将抛出异常。单位为毫秒数;默认为-1,表示永不超时。已废弃,请使用maxWaitDuration
  • minEvictableIdleTimeMillis:连接空闲的最小时间,达到此值后空闲连接将可能会被移除。负值(-1)表示不移除;默认值1000L 60L 30L。已废弃,请使用minEvictableIdleDuration
  • softMinEvictableIdleTimeMillis:连接空闲的最小时间,达到此值后空闲连接将会被移除,且保留minIdle个空闲连接数。已废弃,请使用softMinEvictableIdleDuration
  • numTestsPerEvictionRun:对于空闲连接检测线程而言,每次检测的连接资源的个数。默认值3
  • evictionPolicyClassName:默认值org.apache.commons.pool2.impl.DefaultEvictionPolicy
  • testOnCreate:默认值false
  • testOnBorrow:向调用者输出连接资源时,是否检测是有有效,如果无效则从连接池中移除,并尝试获取继续获取。默认为false。建议保持默认值
  • testOnReturn:默认值false
  • testWhileIdle:向调用者输出连接对象时,是否检测它的空闲超时;默认为false。如果连接空闲超时,将会被移除;建议保持默认值。默认值false
  • timeBetweenEvictionRunsMillis:空闲连接检测线程,检测周期,单位是毫秒数。如果为负值,表示不运行检测线程。默认值为-1。已废弃,请使用durationBetweenEvictionRuns
  • durationBetweenEvictionRuns:
  • blockWhenExhausted:默认值true
  • jmxEnabled:默认值true
  • jmxNamePrefix:默认值pool
  • jmxNameBase:默认值null
  • maxTotal:连接池中最大连接数

参考

相关文章:

池化技术、Commons Pool介绍

概述 池化技术&#xff0c;一种通过重复利用对象实例而非频繁创建和销毁的技术。 常见的可池化对象&#xff1a; 数据库连接(Connection)&#xff1a;数据库连接创建和销毁代价高&#xff0c;连接池广泛用于管理JDBC连接&#xff1b;线程(Thread)&#xff1a;线程的创建和销…...

下载并安装Visual Studio 2017过程

一、下载 1、下载链接 下载链接&#xff1a;官方网址 先登录 往下滑找到较早的下载 2、进行搜索下载 或者直接点击&#x1f517;网站跳转 3、确认系统信息进行下载 二、安装 下载完成后右键使用管理员身份运行 1、点击同意后安装 2、若报错—设置失败 打开控制面板-&g…...

菊风视频能力平台开发服务正式入驻华为云云商店,成为华为云联营联运合作伙伴

日前&#xff0c;菊风视频能力平台开发服务正式入驻华为云云商店&#xff0c;成为华为云在实时音视频领域的联营联运合作伙伴。 菊风结合自身产品方案优势与华为云开放、共盈的生态优势强强联手&#xff0c;在推动金融行业数字化转型的路上又向前迈出了一大步。华为云云商店作为…...

springboot整合kafka

springboot整合kafka pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven…...

Python深度学习框架:PyTorch、Keras、Scikit-learn、TensorFlow如何使用?学会轻松玩转AI!

前言 我们先简单了解一下PyTorch、Keras、Scikit-learn和TensorFlow都是什么。 想象一下你要盖一座大房子。你需要砖头、水泥、工具等等&#xff0c;对吧&#xff1f;机器学习也是一样&#xff0c;需要一些工具来帮忙。PyTorch、Keras、Scikit-learn和TensorFlow就是四种不同的…...

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…...

为什么DDoS防御很贵?

分布式拒绝服务攻击&#xff08;DDoS攻击&#xff09;是一种常见的网络安全威胁&#xff0c;通过大量恶意流量使目标服务器无法提供正常服务。DDoS防御是一项复杂且昂贵的服务&#xff0c;本文将详细探讨为什么DDoS防御如此昂贵&#xff0c;并提供一些实用的代码示例和解决方案…...

将WPS的PPT 无损的用微软的PowerPoint打开

用WPS做了PPT&#xff0c;但是用用PowerPoint打开的时候&#xff0c;老是会有几张图错位。 解决方案&#xff1a;将wps做的PPT另存为PowerPoint的格式 参考博客&#xff1a;解决office的PPT和WPS的PPT不兼容的问题_office ppt和wps中代码不通用-CSDN博客 另存为的时候&#…...

【汇编】uniapp开发

UniApp是一款基于Vue.js构建的跨平台开发框架&#xff0c;可以用于快速开发同时运行在多个平台&#xff08;包括iOS、Android、H5和小程序&#xff09;的应用程序。UniApp的目标是提供一套代码即可在不同平台上运行的开发模式&#xff0c;从而节省开发者的时间和精力。本文将介…...

详解Oracle表的类型(二)

1.引言&#xff1a; Oracle数据库提供了多种表类型&#xff0c;以满足不同的数据存储和管理需求。本博文将对Oracle分区表及使用场景进行详细介绍。 2. 分区表 分区表是Oracle数据库中一种重要的表类型&#xff0c;它通过将表数据分割成多个逻辑部分来提高查询性能、管理灵活…...

Docker--通过Docker容器创建一个Web服务器

Web服务器 Web服务器&#xff0c;一般指网站服务器&#xff0c;是驻留于因特网上某种类型计算机的程序。 Web服务器可以向浏览器等Web客户端提供文档&#xff0c;也可以放置网站文件以供全世界浏览&#xff0c;或放置数据文件以供全世界下载。 Web服务器的主要功能是提供网上…...

Next.js-样式处理

#题引&#xff1a;我认为跟着官方文档学习不会走歪路 Next.js 支持多种为应用程序添加样式的方法&#xff0c;包括&#xff1a; CSS Modules&#xff1a;创建局部作用域的 CSS 类&#xff0c;避免命名冲突并提高可维护性。全局 CSS&#xff1a;使用简单&#xff0c;对于有传统…...

整合Springboot shiro jpa mysql 实现权限管理系统(附源码地址)

一、在开发企业级应用时,权限管理是一个至关重要的功能。本文将围绕 Spring Boot、JPA、MySQL 和 Apache Shiro,构建一个基础的权限管理系统,涵盖用户认证与授权等核心功能。 一、技术选型及框架介绍 Spring Boot:简化 Spring 应用的配置和开发。JPA:实现数据持久化,提供…...

极智嘉嵌入式面试题及参考答案

对于交叉编译器的理解 交叉编译器是一种在一个计算机平台上为另一个不同架构的计算机平台生成可执行代码的编译器。它在嵌入式系统开发中起着关键作用。 从其必要性来看&#xff0c;嵌入式系统通常使用的处理器架构与我们日常使用的 PC 等通用计算机不同&#xff0c;如 ARM、MI…...

【MySQL】数据库核心技术与应用指南

数据库的各种概念 1. 指一门学科《数据库原理与应用》。&#xff08;研究如何设计实现一个数据库&#xff09; 2. 指一类用来管理数据的软件。 3. 指某一个具体的数据库软件。 4. 指部署了某个数据库软件的电脑。 数据库软件 关系型数据库 1. 使用 “表” 的结构来组织数据。…...

23省赛区块链应用与维护(房屋租凭)

23省赛区块链应用与维护(房屋租凭) 背景描述 随着异地务工人员的增多,房屋租赁成为一个广阔市场。目前,现有技术中的房屋租赁是由房主发布租赁信息,租赁信息发布在房屋中介或租赁软件,租客获取租赁信息后,现场看房,并签订纸质的房屋租赁合同,房屋租赁费用通过中介或…...

深度学习4

一、手动构建模型 epoch 一次完整数据的训练过程&#xff08;可细分多次训练&#xff09;&#xff0c;称为 一代训练 Batch 小部分样本对权重的更新&#xff0c;称为 一批数据 iteration 使用一个 Batch 的过程&#xff0c;称为 一次训练 步骤&#xff1a; 1、生成 x,y 的…...

跳绳视觉计数方案

产品概述 提供基于摄像头视觉技术的跳绳计数解决方案&#xff0c;可精准完成跳绳动作的实时计数&#xff0c;效果完全满足考试水平的要求。方案采用先进的计算机视觉算法&#xff0c;结合高效的模型架构&#xff0c;确保计数的准确性和稳定性。适用场景 学校体育考试&#xff…...

TEA加密逆向

IDA伪代码 do{if ( v15 )v17 v38; // x120x0->0x79168ba790&#xff0c; 输入字符串经过check1处理后字符串elsev17 v40;v18 (unsigned int *)&v17[v16]; // 0x78cbbd47fc add x12, x12, x8 ; x120x79168ba790->…...

LeetCode 404.左叶子之和

题目&#xff1a;给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 思路&#xff1a;一个节点为「左叶子」节点&#xff0c;当且仅当它是某个节点的左子节点&#xff0c;并且它是一个叶子结点。因此我们可以考虑对整 node 时&#xff0c;如果它的左子节点是一个叶子…...

01-go入门

文章目录 Go语言学习1. 简介安装windows安装linux安装编译工具安装-goland 2. 入门2.1 Helloworld注释 2.2 变量初始化打印内存地址变量交换匿名变量作用域局部变量全局变量 2.3 常量iota 2.4 数据类型布尔整数浮点类型复数字符串定义字符串字符串拼接符定义多行字符串 map数据…...

【经典】抽奖系统(HTML,CSS、JS)

目录 1、添加参与者 2、多次添加 3、点击抽奖 功能介绍&#xff1a; 使用方法&#xff1a; 完整代码&#xff1a; 一个简单但功能强大的抽奖系统的示例&#xff0c;用于在网页上实现抽奖。 1、添加参与者 2、多次添加 3、点击抽奖 功能介绍&#xff1a; 参与者添加&…...

GoF设计模式——结构型设计模式分析与应用

文章目录 UML图的结构主要表现为&#xff1a;继承&#xff08;抽象&#xff09;、关联 、组合或聚合 的三种关系。1. 继承&#xff08;抽象&#xff0c;泛化关系&#xff09;2. 关联3. 组合/聚合各种可能的配合&#xff1a;1. 关联后抽象2. 关联的集合3. 组合接口4. 递归聚合接…...

Java后端如何进行文件上传和下载 —— 本地版

简介&#xff1a; 本文详细介绍了在Java后端进行文件上传和下载的实现方法&#xff0c;包括文件上传保存到本地的完整流程、文件下载的代码实现&#xff0c;以及如何处理文件预览、下载大小限制和运行失败的问题&#xff0c;并提供了完整的代码示例。 大体思路 1、文件上传 …...

json格式数据集转换成yolo的txt格式数据集

这个代码是参考了两个博客 我是感觉第一篇博客可能有问题&#xff0c;然后自己做了改进&#xff0c;如果我是错误的或者正确的&#xff0c;请各位评论区说一下&#xff0c;感谢 Json格式的数据集标签转化为有效的txt格式(data_coco)_train.json-CSDN博客 COCO&#xff08;.j…...

什么是Three.js,有什么特点

什么是 Three.js&#xff1f; Three.js 是一个基于 WebGL 技术的 JavaScript 3D 库。它允许开发者在网页上创建和展示 3D 图形内容&#xff0c;而无需用户安装任何额外的插件或软件。Three.js 简化了 WebGL 的复杂性&#xff0c;使得即便是对图形编程不太熟悉的人也能快速上手…...

Linux笔记--基于OCRmyPDF将扫描件PDF转换为可搜索的PDF

1--官方仓库 https://github.com/ocrmypdf/OCRmyPDF 2--基本步骤 # 安装ocrmypdf库 sudo apt install ocrmypdf# 安装简体中文库 sudo apt-get install tesseract-ocr-chi-sim# 转换 # -l 表示使用的语言 # --force-ocr 防止出现以下错误&#xff1a;ERROR - PriorOcrFoundE…...

Unity 导出 Xcode 工程 修改 Podfile 文件

Unity 导出 Xcode 工程 修改 Podfile 文件 在 Editor 文件夹下新建 xxx.cs 脚本 实现静态方法 [PostProcessBuild]public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject){// Unity 导出 Xcode 工程自动调用这个方法 }using System.IO; using…...

UE5 slate BlankProgram独立程序系列

源码版Engine\Source\Programs\中copy BlankProgram文件夹&#xff0c;重命名为ASlateLearning&#xff0c;修改所有文件命名及内部名称。 ASlateLearning.Target.cs // Copyright Epic Games, Inc. All Rights Reserved.using UnrealBuildTool; using System.Collections.Ge…...

内存不足引发C++程序闪退崩溃问题的分析与总结

目录 1、内存不足一般出现在32位程序中 2、内存不足时会导致malloc或new申请内存失败 2.1、malloc申请内存失败&#xff0c;返回NULL 2.2、new申请内存失败&#xff0c;抛出异常 3、内存不足项目实战案例中相关细节与要点说明 3.1、内存不足导致malloc申请内存失败&#…...