GlassFish是由Sun Microsystems主导开发、后来移交给Eclipse基金会的开源应用服务器,长期作为Java EE规范的参考实现。它并不是一个轻量级Servlet容器,而是一个完整的Java EE运行时,内置支持EJB、JPA、JMS、JSF、CDI等技术。对于需要运行企业级应用、尤其是EAR包的场景,GlassFish能提供比Tomcat更接近标准规范的能力。不过也正因为功能全面,它的目录结构、域管理、内存占用和配置复杂度都高于Tomcat,很多初次接触的人会在部署和调优时遇到问题。

GlassFish的定位与Tomcat、WildFly的区别
很多人会把GlassFish和Tomcat放在一起比较,但两者的定位从一开始就不同。Tomcat只实现了Servlet和JSP规范,本质上是一个Web容器,适合运行以HTTP请求为核心的应用。GlassFish则是一个完整的Java EE应用服务器,除了Servlet和JSP,还内置了EJB容器、JPA持久化、JMS消息服务、JSF视图框架、CDI依赖注入等。如果你要部署一个包含EJB模块和Web模块的EAR包,Tomcat无法直接处理EJB,而GlassFish可以原生支持。
这种完整性带来便利,也带来成本。GlassFish启动时默认会加载更多服务,内存占用通常在300MB以上,而Tomcat可能只有几十MB。对于小型Web应用,用GlassFish显得有些笨重;对于需要事务管理、消息驱动Bean、分布式调用的企业应用,GlassFish则能减少大量第三方集成工作。另一个常见的对比对象是WildFly,两者都属于完整Java EE应用服务器,但GlassFish更强调标准参考实现身份,WildFly在性能优化和企业功能上更为激进。
下面用表格简单对比三者在典型场景下的差异:
| 特性 | Tomcat | GlassFish | WildFly |
|---|---|---|---|
| 类型 | Servlet容器 | 完整Java EE服务器 | 完整Java EE服务器 |
| EJB支持 | 不支持 | 支持 | 支持 |
| JPA/JMS内置 | 否 | 是 | 是 |
| 管理控制台 | 简单 | 功能较全 | 功能较全 |
| 内存占用 | 低 | 较高 | 较高 |
| 适合场景 | 纯Web应用 | 标准企业应用 | 复杂企业应用 |
从表格可以看出,如果你的项目只是几个Servlet和JSP页面,完全没有必要上GlassFish;如果项目已经按照Java EE规范设计了EJB、JPA等模块,GlassFish可以提供最接近规范的行为,减少因为容器差异导致的兼容问题。
GlassFish核心架构与安装部署要点
GlassFish的核心管理单位叫域(domain),一个域就是一个独立的运行环境,拥有自己的配置、日志、部署应用和端口。每个域中有一个域管理服务器(DAS),负责接收管理命令和同步配置。单机部署通常只需要一个域,集群环境下可以创建多个实例,由DAS统一管理。理解域的概念对排查问题很重要,很多配置文件、日志和部署目录都位于对应域目录下。
安装GlassFish的步骤并不复杂。以Windows环境为例,下载GlassFish压缩包后解压到指定目录,例如C:\glassfish7,然后进入C:\glassfish7\bin目录,运行asadmin start-domain即可启动默认域。如果系统已经安装JDK,需要先确保JAVA_HOME环境变量指向有效JDK路径。启动成功后浏览器访问http://localhost:4848即可打开管理控制台,默认管理员账号通常需要初始化设置。在Linux或macOS下路径类似,只是bin目录下的脚本名称为asadmin,不需要后缀。
部署应用有三种常见方式。第一种是通过管理控制台上传war或ear包,操作直观但不利于自动化;第二种是使用asadmin deploy命令,例如asadmin deploy C:\apps\myapp.war,适合脚本化部署;第三种是将应用包放入域目录下的autodeploy文件夹,GlassFish会自动检测并部署。无论哪种方式,部署后都可以通过asadmin list-applications查看应用状态。如果部署失败,优先查看域目录下的logs/server.log,里面通常有明确的异常堆栈。
这里需要特别注意路径中的反斜杠。在Windows命令行中,目录分隔符使用反斜杠,比如C:\glassfish7\bin\asadmin。如果写成C:/glassfish7/bin/asadmin,虽然部分命令可能兼容,但日志和配置中的路径会不一致,排查问题时容易混淆。
常见问题解答汇总
下面是使用GlassFish时高频出现的问题和处理思路。这些问题大多与域配置、端口、JDBC和内存有关,解决一个往往能避免后续反复踩坑。
1. 启动时报端口被占用怎么办
GlassFish默认使用8080作为HTTP端口,4848作为管理端口,还有8009、8181等端口。如果启动失败并提示端口已被占用,可以用netstat -ano | findstr 8080查看占用进程。在Windows上使用taskkill /PID 进程号 /F结束进程,或者修改GlassFish的端口配置。端口配置文件位于域目录下的config/domain.xml,搜索8080可以找到对应http-listener,替换成其他端口后重启域即可。
2. 管理控制台无法访问
管理控制台无法访问通常有三个原因:域没有启动、防火墙拦截、管理端口配置错误。先确认asadmin list-domains显示域正在运行,再检查4848端口是否监听。如果服务正常但页面打不开,查看server.log中是否有绑定失败信息。有时修改了管理员密码后浏览器缓存的旧会话会导致登录异常,换用无痕窗口测试可以快速排除。
3. 部署应用时出现ClassNotFound或NoClassDefFoundError
这类错误大多和类库冲突或依赖缺失有关。GlassFish本身带有大量Java EE API,如果应用内的lib目录又打包了相同或冲突的jar,部署后可能出现类加载问题。可以检查应用包中是否包含了servlet-api.jar、javaee-api.jar等,这些应该由容器提供,不应该打包进应用。如果确实需要特殊版本,可以通过GlassFish的类加载器策略调整,但更推荐先清理重复依赖。
4. JDBC连接池配置后连接不上数据库
JDBC连接池是GlassFish使用数据库时的常用配置,但连接失败很常见。首先确认JDBC驱动jar已经放入GlassFish的lib目录或域目录下的lib,并且连接池的URL、用户名、密码正确。在管理控制台中测试连接池时,如果报No suitable driver说明驱动没有加载;如果报Connection refused说明数据库地址或端口不对;如果报Access denied则是账号权限问题。另外要检查连接池的ping参数是否开启,否则连接超时后无法自动恢复。
5. 内存溢出或频繁Full GC
GlassFish默认堆内存可能不足以运行大型应用,可以在启动域时通过asadmin create-jvm-options设置-Xmx和-Xms。例如asadmin create-jvm-options -Xmx2048m:-Xms1024m。如果应用有内存泄漏,建议结合jmap和jstat观察堆使用趋势,定位对象增长来源。单纯调大堆内存只能拖延问题,最终还需要从代码层面修复。
6. 修改配置后不生效
很多配置修改后需要重启域才能生效,尤其是domain.xml中的网络监听器和线程池参数。有些动态配置可以通过asadmin set命令即时修改,但不同版本支持情况不同。如果重启后配置仍不生效,检查是否修改了错误的域或实例,GlassFish集群环境下每个实例可能有独立配置,需要在正确层级操作。
生产环境使用GlassFish的建议
虽然GlassFish在轻量级场景下不如Tomcat流行,但在需要标准Java EE能力的项目中仍然有稳定表现。生产环境使用前,建议完成三件事:第一,根据应用规模调整JVM参数,避免默认堆内存偏小;第二,配置监控和日志轮转,server.log长期不清理会占满磁盘;第三,定期备份域目录,迁移或恢复环境时直接复制整个domain目录是最快的方式。
此外,不要在生产环境长期使用开发模式启动域。开发模式下热部署和自动加载会带来额外开销,正式环境应该使用asadmin start-domain --production=true启动,或者修改域配置关闭自动部署和调试选项。安全方面,管理控制台不要暴露在公网,修改默认密码并限制访问IP,生产集群建议启用HTTPS管理协议。
总体来说,GlassFish的价值在于它严格遵循Java EE规范,适合教学、标准验证和规范驱动的企业项目。如果你的团队已经熟悉Tomcat,迁移到GlassFish需要一定的学习成本,但一旦掌握域管理和配置体系,很多问题都能通过日志和官方文档快速定位。希望这篇梳理能让你对GlassFish有一个清晰完整的认识,在实际项目中少走弯路。

