About Java's ClassLoader

Not much to say about theory, I am not good at theory. Here is an article about ClassLoad, which is very detailed: Java ClassLoad Details

What I am talking about here is that I have encountered a problem in actual development. It is like this. In the past, there was a requirement to crawl websites of multiple daily newspapers every day. Then I wrote a crawler framework myself. Each daily newspaper implements a crawling rule class in java. The framework will select the newspapers that need to be crawled that day, and start a daily task for these newspapers without any newspapers. For newspapers, try to crawl every half hour, and crawl until the data ends the task. However, for the rules, some websites often change, and the crawling rules need to be updated accordingly. So the question is, what if the rules are updated?

The easiest solution is to re-upload the rules, restart Tomcat, and keep running. Obviously it is not realistic. Later, through the research of ClassLoader, I implemented a ClassLoader by myself, so that the class is re-read every time the class is loaded.

The following is the implementation of my MyClassLoader, and the test method

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
 *
 * @author yun
 * @date 2015年3月26日
 * @time 下午3:21:38
 * @todo 以字节数据读取类文件并加载
 *
 */
public class MyClassLoader extends ClassLoader {
	
	public MyClassLoader() {
		super(MyClassLoader.class.getClassLoader());
	}

	public Class<?> forName(String name) throws Exception {
		String path = "/" + name + ".class";
		InputStream is = System.class.getResourceAsStream(path);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int size = 0;
		while ((size = is.read()) != -1) {
			baos.write(size);
		}
		byte[] classData = baos.toByteArray();
		baos.close();
		is.close();
		return super.defineClass(name, classData, 0, classData.length, null);
	}
}


test

task class

import java.text.SimpleDateFormat;
import java.util.Date;
 
public class Task {
     
	private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss ");
	
    public void execute() {
        //执行任务
        System.out.println(format.format(new Date()) + "Just A Test");//输出语句a
        System.out.println(format.format(new Date()) + "The Other Test");//输出语句b
    }
}

Quartz Timing Job

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class ActionJob implements Job {

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		while (true) {
			try {
				String path = "Task";
				// 加载任务类
				Class<?> clas = Class.forName(path);//默认ClassLoad
//				Class<?> clas = new MyClassLoader().forName(path);//我自己实现的ClassLoad
				Object o = clas.newInstance();// 实例化已任务类对象
				// 获取启动方法,并启动
				clas.getMethod("execute").invoke(o);
				Thread.sleep(20000);//每隔20秒加载并执行一次Task
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

main method entry

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

public class Start {

	public static void main(String[] args) {
		try {
			StdSchedulerFactory factory = new StdSchedulerFactory();
			Scheduler scheduler = factory.getScheduler();
			JobDetail detail = newJob(ActionJob.class)
					.withIdentity("d_name", "d_group")
					.build();
			Trigger trigger = newTrigger()
					.withIdentity("t_name", "t_group")
					.startNow()
					.build();
			scheduler.scheduleJob(detail, trigger);
			scheduler.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

testing method:

1. Load the task class with the default ClassLoader, only open the output statement a, compile and obtain four class files

2. Load the task class with the default ClassLoader, open the output statements a and b, and compile to obtain four class files

3. Load the task class with MyClassLoader, only open the output statement a, compile and obtain four class files

4. Load the task class with My ClassLoader, open the output statements a and b, compile and obtain four class files

Execute Start in 1, output statement a every 20 seconds, do not stop copying the Task.class file in 2 to the Task.class in 1, continue to observe the output, you will find an output statement a, and then delete it Task.class file, continue to observe the output, the result is to continue to output statement a


It can be seen that the program is still executed after deleting Task.class, indicating that modifying Task.class will not affect the execution of the task


Then stop the previous character, execute Start in 3, only output statement a, and then modify the Task.class in 4 to cover the one in 3, continue to observe the data, and you will find that both output statements a and b are available.

After removing Task.class

An exception is reported, indicating that the task class is re-read and loaded every time through MyClassLoad.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325915840&siteId=291194637