実行時にクラスファイルを作成しています。
クラスローダーで既存のクラスファイルを更新したものに置き換えたいです。
これは、サーバーの再起動と再デプロイを回避するホット スワップ (JRebel など) に似ています。
コンテキストをリロードするための tomcat の context.xml アプローチを見つけました。ただし、本番環境の場合はあまり役に立ちません。
実行時に ClassLoader にクラスを登録できますか? 実行時にクラスをリロードする代替手段があるかどうかを提案してください。
次のコードを使用して、現在の classLoader を取得しています。
ClassLoader classLoader = LoggingAspect.class.getClassLoader();
以下はロードクラスメソッドの実装です。
public class AspectClassLoader extends ClassLoader{
@Override
public synchronized Class<?> loadClass(String name) throws ClassNotFoundException
{
String customLoadClass = "com.log.LoggingAspect";
try
{
if(!customLoadClass.equals(name))
{
return super.loadClass(name);
}
else
{
URL classLoadUrl = new URL(this.reloadClassUrl);
URLConnection connection = classLoadUrl.openConnection();
InputStream input = connection.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int data = input.read();
while(data != -1){
buffer.write(data);
data = input.read();
}
input.close();
byte[] classData = buffer.toByteArray();
return defineClass(name, classData, 0, classData.length);
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
クラスをリロードするには、次のコードを使用しています。
AspectClassLoader urlClsLoader = new AspectClassLoader(classLoader);
Class aspect = urlClsLoader.reloadClass("com.log.LoggingAspect", true, new String("file:"+className));
クラスローダーの私の reload メソッドは
public synchronized Class<?> reloadClass(String name, boolean resolve, String reloadClassUrl) throws ClassNotFoundException
{
this.reloadClassUrl = reloadClassUrl;
return this.loadClass(name, resolve);
}
LoggingAspect の新しいインスタンスを作成するとリロードした後も、古いインスタンスが表示されます。提案してください。
Class aspect = urlClsLoader.reloadClass("com.log.LoggingAspect", true, new String("file:"+className));
com.log.aspect.Aspect aspectObj = (com.log.aspect.Aspect)aspect.newInstance();
それでも私は古いインスタンスを取得しています。
classloader が変更されたクラスをロードしない理由を教えてください。