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

Quarkus Keycloak Admin Client闲置后触发ClassNotFoundException问题

解决Quarkus开发模式下Keycloak Admin Client闲置后ClassNotFoundException问题

问题原因

  1. Quarkus开发模式启用了类加载优化,闲置15分钟以上时,未被持续引用的类(如org.keycloak.representations.AccessTokenResponse)会被JVM卸载
  2. 手动构建Keycloak实例时,未绑定Quarkus的上下文类加载器,后续重新获取Token时无法加载已卸载的类
  3. TokenManager内部的RestClient代理在闲置后丢失类加载上下文,导致反序列化Token响应时失败

解决方案

方案1:使用Quarkus原生CDI注入管理Keycloak实例

利用quarkus-keycloak-admin-rest-client提供的自动注入能力,让Quarkus容器管理实例生命周期和类加载上下文,彻底避免手动管理的问题。

  1. 在application.properties中配置Keycloak Admin Client参数:
quarkus.keycloak-admin-client.server-url=http://localhost:8111
quarkus.keycloak-admin-client.realm=quarkus
quarkus.keycloak-admin-client.client-id=admin-rest-client
quarkus.keycloak-admin-client.client-secret=你的客户端密钥
quarkus.keycloak-admin-client.username=你的管理员账号
quarkus.keycloak-admin-client.password=你的管理员密码
quarkus.keycloak-admin-client.grant-type=password
  1. 注入Keycloak实例并使用:
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.RealmRepresentation;

@ApplicationScoped
public class KeycloakAdminService {

    @Inject
    Keycloak keycloak;

    public boolean verifyConnection(String realmName) {
        try {
            RealmResource realmResource = keycloak.realm(realmName);
            UsersResource usersResource = realmResource.users();
            
            System.out.println("Realm内用户数量: " + usersResource.count());
            RealmRepresentation realmRep = realmResource.toRepresentation();
            System.out.println("Realm显示名称: " + realmRep.getDisplayName());
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

方案2:手动构建时强制绑定Quarkus上下文类加载器

如果必须手动创建Keycloak实例,在操作前后切换线程的上下文类加载器,确保使用Quarkus的类加载器加载相关类。

修改你的doConnectToKeycloak方法:

private Boolean doConnectToKeycloak(String host, String realm, String clientId, String clientSecret, String username, String password) {
    ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
    try {
        // 切换为Quarkus上下文类加载器
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        
        if (keycloak != null) {
            try {
                keycloak.close();
            } catch (Exception e) {
                System.out.println("关闭现有连接警告: " + e.getMessage());
            }
        }

        keycloak = KeycloakBuilder.builder()
                .serverUrl("http://" + host)
                .realm(realm)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .grantType(OAuth2Constants.PASSWORD)
                .username(username)
                .password(password)
                .build();

        realmResource = keycloak.realm(realm);
        if (realmResource != null) {
            UsersResource usersResource = realmResource.users();
            System.out.println("Realm内用户数量: " + usersResource.count());
            RealmRepresentation tmpRes = realmResource.toRepresentation();
            System.out.println("Realm显示名称: " + tmpRes.getDisplayName());
            realmIsOk = true;
        } else {
            System.out.println("无法获取Realm资源");
            realmIsOk = false;
        }
    } catch (Exception e) {
        System.out.println("连接失败: " + e.toString());
        e.printStackTrace();
        realmIsOk = false;
    } finally {
        // 恢复原类加载器
        Thread.currentThread().setContextClassLoader(originalClassLoader);
    }
    return realmIsOk;
}

方案3:临时禁用开发模式类卸载(仅调试用)

在application.properties中添加配置,关闭JVM类卸载功能,避免闲置时类被回收,但会增加内存占用,不建议长期使用:

quarkus.class-loader.enable-jvm-class-unloading=false

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:24:49