内容提要
本文讨论了在OpenResty中实现Java类热重载的过程。通过创建新的类加载器并打破父委托模型,作者实现了一个动态类加载器,允许在不修改现有Java应用代码的情况下进行类重载。使用时,只需在调用ngx.load_ffi()时在类名后加问号。
延伸解读
类加载器的父委托模型与打破方式
Java类加载器默认采用父委托模型:加载类时先委托父加载器查找,找不到才自己加载。这种机制导致类一旦被加载就会缓存,无法直接重载。本文通过创建新的DynamicClassLoader并重写loadClass方法,对特定包下的类优先自己加载,从而打破父委托,实现每次加载都使用新类加载器,达到热重载目的。
非侵入式热重载的实现关键
热重载需要满足两个条件:每次创建新的类加载器,以及打破父委托模型。本文的实现中,DynamicClassLoader仅对初始化类所在包内的类进行自定义加载,其他依赖类(如gson、freemarker)仍交由父加载器处理,确保它们只加载一次。这样无需修改现有Java应用代码,实现了非侵入式的类重载。
使用方式与注意事项
在OpenResty中调用ngx.load_ffi()时,只需在Java类名后添加问号作为后缀,例如"demo.http2.App?,init,",即可触发动态类加载器进行热重载。注意,该机制仅对同一包下的类生效,其他依赖类仍遵循默认加载方式。此外,不能依赖线程上下文类加载器自动生效,必须显式使用。
Q&A
什么是Java类热重载?
Java类热重载是指在不修改现有Java应用代码的情况下,动态加载和替换Java类的过程。
如何在OpenResty中实现Java类热重载?
在OpenResty中实现Java类热重载需要创建新的类加载器并打破父委托模型,使用时在调用ngx.load_ffi()时在类名后加问号。
Java类加载器的父委托模型是什么?
父委托模型是指类加载器在加载类时,首先会尝试从其父类加载器中查找类,如果找不到才会自己加载。
为什么需要打破父委托模型进行类重载?
打破父委托模型是为了允许新的类加载器加载类,从而实现类的动态重载,而不受限于已加载类的缓存。
在使用Java类热重载时,如何调用新的类?
在调用新的类时,只需在类名后加问号,例如:ngx.load_ffi('ffi_java', 'demo.http2.App?,init,')。
动态类加载器的作用是什么?
动态类加载器允许在不修改现有代码的情况下,动态加载和重载Java类,支持热重载功能。