Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to change the way a class in the jar package runs

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces "how to change the operation mode of a class in the jar package". In the daily operation, I believe many people have doubts about how to change the operation mode of a class in the jar package. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts about "how to change the operation mode of a class in the jar package". Next, please follow the editor to study!

For example:

Classful Feature

Java code

Public class Feature {private String content; public void show () {System.out.println (this.content);}}

And quasi-Function

Java code

Public class Function {private Feature f; public void show () {this.f.show ();}}

The test class Test, the running result is null. And you want him to export hello kitty.

Java code

Public class Test {/ * @ param args * / public static void main (String [] args) {Function function = new Function (); function.show ();}}

* the method you can think of is to directly create a class with the same name of the same package in your eclipse or other compilation environment, and then change the relevant method to the one you want, as follows:

Java code

Public class Feature {private String content; public Feature () {this.content = "hello kitty";} public void show () {System.out.println (this.content);}}

Then, you will find that you use your class An instead of the one in the jar bag.

But what happens if your program is also packed into a jar package and run with the original jar?

You may find that you will output null, or if you are lucky, you may output hello kitty.

Why is that? Because when there is a class of the same name with the same package, classLoader always tries to load one first, and after loading into this class file, it will not be loaded again; this first loaded class is generally related to the order of classpath settings.

In the eclipse environment, the class under the editor will be loaded first, and then the imported class library will be loaded first.

If you load into your class first, you will output "hellokitty".

If you need to specify your class to be loaded in the production environment

And,

You can't predict how customers will prioritize classPath, so what are you going to do?

Can you write a classLoader that only loads the target class and let your calling program run in this classLoader environment?

Let us try try: write this special classLoader first

Java code

Public class HoneyLoader extends URLClassLoader {public HoneyLoader (URL [] urls, ClassLoader parent) {super (urls, parent);} public synchronized Class loadClass (String name) throws ClassNotFoundException {Class c = findLoadedClass (name); if (c! = null) {return c } / / find it in the specified location (specified by urls) first, but cannot find it to the parent class try {c = this.findClass (name);} catch (Exception e) {c = super.loadClass (name);} return c;}}

Go back to our test class and modify it as follows

Java code

Public class Test {public static void main (String [] args) throws Exception {/ / according to the jar package name, get the name of the jar package we need: url String jarName = "feature2.jar"; URL url = null; ClassLoader loader = Thread.currentThread (). GetContextClassLoader (); Enumeration urls = loader.getResources ("Feature.class"); int I = 0 While (urls.hasMoreElements ()) {url = urls.nextElement (); I = url.getPath () .indexOf (jarName); if (I >-1) {break }} / / launch our runtime environment with honeyLoader ClassLoader myLoader = new HoneyLoader (new URL [] {new URL (url.getPath (). Substring (0, I) + jarName)}, loader); Object object = myLoader.loadClass ("Feature"). NewInstance (); object.getClass (). GetMethod ("show") .invoke (object) }

Running result:

Java code

Hello kitty

With the method of classLoader, a small running mechanism will be established, which has a low correlation with the business code and a lot of redundant code.

Moreover, the new package name and class that are the same as the original class are not easy to maintain

Is there a better way?

For the requirements described in (1), in fact, we only need to change the private attribute content of Feature, can it be realized through reflection?

Try the following code:

Java code

Public class Test {/ / get the attributes of object fieldName public static Field getField (Object object, String fieldName) throws Exception {Field field = object.getClass () .getDeclaredField (fieldName); return field;} public static void main (String [] args) throws Exception {Function function = new Function () / / get feature Field f_feature of function = getField (function, "f"); / / get its attribute content f_feature.setAccessible (true) through feature; Field f_function = getField (f_feature.get (function), "content") / / change the content of content f_function.setAccessible (true); f_function.set (f_feature.get (function), "hello kitty"); function.show ();}}

Execute, get the result

Java code

Hello kitty

Redundant code is reduced, the purpose is more clear, but for the changed business code, it is still not clear; it is not easy to maintain

Usually, if we want to get a class with our characteristics, we usually use inherited methods, but sometimes, we will find that if it is the class you want to call, if you want to change the action a little bit, then you have to inherit calls and invocations in order to change the invocation of the call.

If we only change the target class, inherit only the target class, combined with reflection, and change the call, is it feasible?

For example, inherit Feature to create the class MyFeature

Java code

Public class MyFeature extends Feature {private String mycontent; public MyFeature () {this.mycontent = "hello kitty";} public void show () {System.out.println (this.mycontent);}}

In this way, the logic of our change is much clearer and easier to maintain, so let's modify the Test class.

Java code

Public class Test {/ / get the attributes of object fieldName public static Field getField (Object object, String fieldName) throws Exception {Field field = object.getClass () .getDeclaredField (fieldName); return field;} public static void main (String [] args) throws Exception {Function function = new Function () / / get feature Field f_feature of function = getField (function, "f"); / / change the content of feature f_feature.setAccessible (true); f_feature.set (function, new MyFeature ()); function.show ();}}

At this point, the logic of Test is much clearer, and we can clearly see which class we need to change.

Run it and see the results.

Java code

Hello kitty at this point, the study on "how to change the way a class in the jar package runs" is over. I hope to be able to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report