You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 3.3.2修改控制器后热重载触发静态初始化器异常求助

Grails热重载失败,Spring Security类抛出IllegalAccessError

问题背景

你在修改控制器后,从Grails交互式提示符执行compile命令触发了热重载故障,抛出一系列IllegalAccessError,涉及带有@GrailsCompileStatic注解的Spring Security相关Groovy类(Requestmap、Role、User、UserRole)。项目环境为Grails 3.3.2、spring-security-core 3.3.2、spring-security-rest 2.0.0.M2、JDK 1.8。

错误日志如下:

2018-01-26 19:37:43.752 ERROR --- [Loader@14dad5dc] o.s.loaded.CurrentLiveVersion : 调用com.emmanuj.cleena.Requestmap的静态初始化器时出现意外异常
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springsource.loaded.CurrentLiveVersion.runStaticInitializer(CurrentLiveVersion.java:311)
	at org.springsource.loaded.ReloadableType.loadNewVersion(ReloadableType.java:433)
	at org.springsource.loaded.TypeRegistry.loadNewVersion(TypeRegistry.java:1018)
	at org.springsource.loaded.agent.ReloadableFileChangeListener.fileChanged(ReloadableFileChangeListener.java:104)
	at org.springsource.loaded.agent.Watcher.determineChangesSince(FileSystemWatcher.java:251)
	at org.springsource.loaded.agent.Watcher.run(FileSystemWatcher.java:235)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalAccessError
	at com.emmanuj.cleena.Requestmap$$EQhtIzZ2.___clinit___(Requestmap.groovy)
	... 11 more
2018-01-26 19:37:43.770 ERROR --- [Loader@14dad5dc] o.s.loaded.CurrentLiveVersion : 调用com.emmanuj.cleena.Role的静态初始化器时出现意外异常
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springsource.loaded.CurrentLiveVersion.runStaticInitializer(CurrentLiveVersion.java:311)
	at org.springsource.loaded.ReloadableType.loadNewVersion(ReloadableType.java:433)
	at org.springsource.loaded.TypeRegistry.loadNewVersion(TypeRegistry.java:1018)
	at org.springsource.loaded.agent.ReloadableFileChangeListener.fileChanged(ReloadableFileChangeListener.java:104)
	at org.springsource.loaded.agent.Watcher.determineChangesSince(FileSystemWatcher.java:251)
	at org.springsource.loaded.agent.Watcher.run(FileSystemWatcher.java:235)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalAccessError
	at com.emmanuj.cleena.Role$$EQhtIzZ2.___clinit___(Role.groovy)
	... 11 more
2018-01-26 19:37:43.827 ERROR --- [Loader@14dad5dc] o.s.loaded.CurrentLiveVersion : 调用com.emmanuj.cleena.User的静态初始化器时出现意外异常
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springsource.loaded.CurrentLiveVersion.runStaticInitializer(CurrentLiveVersion.java:311)
	at org.springsource.loaded.ReloadableType.loadNewVersion(ReloadableType.java:433)
	at org.springsource.loaded.TypeRegistry.loadNewVersion(TypeRegistry.java:1018)
	at org.springsource.loaded.agent.ReloadableFileChangeListener.fileChanged(ReloadableFileChangeListener.java:104)
	at org.springsource.loaded.agent.Watcher.determineChangesSince(FileSystemWatcher.java:251)
	at org.springsource.loaded.agent.Watcher.run(FileSystemWatcher.java:235)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalAccessError
	at com.emmanuj.cleena.User$$EQhtIzZ2.___clinit___(User.groovy)
	... 11 more
2018-01-26 19:37:43.897 ERROR --- [Loader@14dad5dc] o.s.loaded.CurrentLiveVersion : 调用com.emmanuj.cleena.UserRole的静态初始化器时出现意外异常
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springsource.loaded.CurrentLiveVersion.runStaticInitializer(CurrentLiveVersion.java:311)
	at org.springsource.loaded.ReloadableType.loadNewVersion(ReloadableType.java:433)
	at org.springsource.loaded.TypeRegistry.loadNewVersion(TypeRegistry.java:1018)
	at org.springsource.loaded.agent.ReloadableFileChangeListener.fileChanged(ReloadableFileChangeListener.java:104)
	at org.springsource.loaded.agent.Watcher.determineChangesSince(FileSystemWatcher.java:251)
	at org.springsource.loaded.agent.Watcher.run(FileSystemWatcher.java:235)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalAccessError
	at com.emmanuj.cleena.UserRole$$EQhtIzZ2.___clinit___(UserRole.groovy)
	... 11 more

问题分析

这个问题核心是Grails的Spring Loaded热重载机制和@GrailsCompileStatic注解的兼容性冲突。当带有该注解的类被重新加载时,Spring Loaded无法正确处理静态初始化块的访问权限,导致IllegalAccessError。手动执行compile命令会触发额外的类编译和加载逻辑,进一步加剧了这个冲突。

解决方案

临时应急方案

  • 重启应用:这是最快恢复开发的方式,重启后热重载会回到正常状态,只是会损失一点开发时间。
  • 避免手动执行compile:Grails 3.x默认会自动监听文件变化并编译,手动执行compile属于重复操作,容易触发类加载冲突,尽量依赖自动编译。

长期修复方案

  1. 升级插件版本
    你使用的spring-security-rest是M2预览版,存在兼容性问题的概率较高。建议升级到正式稳定版(比如2.0.0+),同时把spring-security-core升级到同系列的最新稳定版(比如3.3.4),新版本通常会修复这类热重载的兼容性bug。

  2. 配置Spring Loaded排除特定类
    在项目的build.gradle中添加配置,让Spring Loaded不参与这些Spring Security类的热重载,避免触发静态初始化的权限问题:

    grails {
        agent {
            springloaded {
                excludes = [
                    'com.emmanuj.cleena.Requestmap',
                    'com.emmanuj.cleena.Role',
                    'com.emmanuj.cleena.User',
                    'com.emmanuj.cleena.UserRole'
                ]
            }
        }
    }
    

    配置后,这些类修改后需要重启应用才能生效,但其他类的热重载不受影响。

  3. 调整@GrailsCompileStatic的使用方式
    如果不是必须在类级别使用@GrailsCompileStatic,可以改为在特定方法上使用@CompileStatic注解,减少静态初始化逻辑的范围,降低冲突概率。如果只是调试阶段,也可以暂时移除类上的该注解,确认问题根源后再做调整。

  4. 升级Grails版本
    Grails 3.3.2属于较早的版本,后续的3.3.x版本(比如3.3.11)对Spring Loaded的兼容性做了不少优化,升级后可能直接解决这个问题。

内容的提问来源于stack exchange,提问作者Emmanuel John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:48:31