1. 调整JVM内存参数
优化JVM堆内存配置是减少JSP内存使用的核心手段。在Tomcat的catalina.sh(或setenv.sh)文件中,设置合理的初始堆大小(-Xms)和最大堆大小(-Xmx),避免频繁垃圾回收(如-Xms1024m -Xmx2048m)。对于Java 8及以上版本,替换永久代为元空间(-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m),防止元空间溢出。同时,选择适合高并发的垃圾收集器(如G1GC,-XX:+UseG1GC),并通过-XX:MaxGCPauseMillis=100限制最大停顿时间,提升内存回收效率。
2. 优化JSP页面代码
减少JSP中的Java代码(Scriptlet),将业务逻辑迁移至Servlet或JavaBean,通过EL表达式(${})和JSTL标签(如<c:forEach>)替代原生Java代码,降低页面解析负担。启用JSP预编译(Tomcat可通过jsp-config配置),将JSP提前编译为Servlet,避免每次请求时的编译开销。压缩JSP页面(如通过gzip过滤器),减少传输数据量,间接降低内存占用。
3. 配置Tomcat线程池
合理设置Tomcat线程池参数,避免线程过多导致内存消耗激增。在server.xml的Connector配置中,调整maxThreads(最大线程数,建议200-500,根据CPU核心数调整)、minSpareThreads(最小空闲线程数,建议25-50)和acceptCount(等待队列长度,建议100-200),平衡并发处理能力和内存使用。
4. 使用缓存技术
引入缓存减少重复计算和数据库访问。对于不变数据(如配置信息),使用内存缓存(如EHCache、Guava Cache)或分布式缓存(如Redis),设置合理的过期时间(如1小时),避免每次请求都从数据库加载。对于静态资源(如CSS、JS、图片),通过Nginx反向代理缓存,减少Tomcat的内存处理压力。
5. 优化数据库访问
减少数据库查询次数,通过批量操作(如batchInsert)替代循环单条插入,使用连接池(如HikariCP)管理数据库连接,提高连接复用率(设置maxPoolSize为20-50)。优化SQL语句,避免全表扫描(添加索引)、不必要的关联查询(使用select指定字段),降低数据库返回的数据量,从而减少JSP处理时的内存占用。
6. 监控与排查内存泄漏
使用监控工具(如JConsole、VisualVM、Prometheus+Grafana)实时监控Tomcat的内存使用情况(堆内存、元空间、线程数),观察GC频率(如Full GC次数过多)和停顿时间。启用GC日志(-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/gc.log),分析GC趋势。若发现内存持续增长,使用Eclipse MAT(Memory Analyzer Tool)分析堆转储(通过jmap -dump:format=b,file=heap.bin <pid>获取),定位内存泄漏点(如静态集合、ThreadLocal未清理、未关闭的资源),并及时修复代码。
7. 系统层面优化
调整Ubuntu系统的内核参数,提高内存管理效率。修改/etc/sysctl.conf,增加半连接队列大小(net.ipv4.tcp_max_syn_backlog=4096)、系统最大文件描述符数(fs.file-max=65535),并执行sysctl -p使配置生效。调整/etc/security/limits.conf,增加用户进程的文件描述符限制(* soft nofile 40960 * hard nofile 40960),避免因文件描述符不足导致的内存分配失败。对于内存紧张的服务器,可添加交换空间(sudo fallocate -l 2G /swapfile,sudo mkswap /swapfile,sudo swapon /swapfile),缓解物理内存压力。