1. Reasons for splitting applications into multiple independent components:
a) Different applications can share the same components. You don't have to make a separate copy of each application.
b) The application changes over time. If you make a smile change to a component of the application, you should re-deploy the component without re-deploying the entire application.
c) The application is dynamic. Depending on the runtime, the application may add new resources (data and code) during the development period (data and code)
d) Applications use resources such as graphic images. These resources are not managed by programmers, and they are not required to be configured.
e) Applications typically contain configuration settings specified by deployment. These settings are the logical part of the application, but only can be used at runtime.
2. On the Java platform, assemble applications at runtime will encounter these issues:
a) Component platform should implement an infrastructure to locate each component of the application to re-assemble.
b) After finding the component, the platform should verify that this component is really working together with the application. (Configuration problem, security issues)
3. The goal of the class loader architecture is to achieve transparency, scalability, rich feature and configurability. In addition, you need to properly process the problem of naming conflicts and version incompatibility, without affecting the ability of sharing from different locations, which is loaded in different ways. Finally, some security measures must be defined to determine some specific control mechanisms, indicating what the dynamically loaded class can do, what can not do.
4. Implicit class load: When a class references another class, use the same class loader with the load reference class implicitly. Trigger implicitly loaded is a referenced compile time type. The subtle difference between the reference type (Class, Object) and the reference class is allowed to be implicit and explicitly loaded.
Code case:
Public class loadme extends loadmebase {
Static loadmetoo lmt = new loadingMetoo ();
Static loadMealso LMA;
Static ClassLoader LDR = GetSomeloader ();
Static class cls = ldr.loadclass ("loadmethree");
Static Object Obj = CLS.NEWINSTANCE ();
}
Note: All red classes will be loaded using loaded Loadme's class loaders because they are referenced by Loadme. and
LoadMealso will not be loaded because it is only initialized to null. LoadMethree, because it is not straightfor
The compile time type of the reference is then used, so it can be loaded by other type loaders (LDR).
5. Class loader rules:
a) Consistency rules: The type loader cannot load the same class multiple times.
b) Prustolic rules: Before loading a class, the class loader general reference parent class loader.
c) Visibility rules: Class can only see other classes that are loaded by their class loaders, the delegate is the class's loader and all its parent class loaders.
6. Entrusted to use it as a namespace
The class loader commissioned a namespace. When considering class loading, the concept of named space not only contains classes, but also the class loader loaded.
Public class loadme {
STATIC {
System.out.println (loadme.class "loading);}
Public loadme () {
System.out.println ("New Instance Created");
}
}
Import java.net. *;
Public class loadingdemo {
Public static void main (string [] args) throws exception {
URL URL = New URL ("File: Sub /");
URL [] URLS = New URL [] {URL};
UrlclassLoader Loader1 = New UrlclassLoader (URLS);
UrlclassLoader Loader2 = New UrlclassLoader (URLS);
Class C1 = loader1.loadClass ("LoadMe");
Class C2 = loader2.loadclass ("loading");
Object O1 = c1.newinstance ();
Object O2 = C2.NEWINSTANCE ();
System.out.println ("(C1 == C2) IS" (C1 == C2));
}
}
First run:
Setting: classpath = .;
Output: Class Loadme Loadded
New Instance Created
Class Loadme Loadded
New Instance Created
(C1 == C2) IS FALSE
Description: When you need to load Loadme, the type-loader loaded loadMedemo will first entrust her parent class loader, that is, the system class loading
The device is loaded, but since she did not find this class under the current class path, the class load will be respectively by Loader1 and Loader2, respectively.
Complete, so we can see that LoadMe is loaded twice in the output. Moreover, C1 and C2 are not the same. Here
It is not the same because the class loader is also part of the namespace.
Second operation: classpath = .; ... / sub/
Output: Class Loadme Loadded
New Instance Created
New Instance Created
(C1 == C2) IS TRUE
Description: This is the same as that, when delegated to the system class loader, she is loaded into the class in ... / sub / down, so it is not used
Loader1 and Loader2 are loaded on loadme, so there is only one "class loadme loadded" in the output, and
C1 is also the same as C2.
Summary: It can be seen from the above situation. Due to the existence of the entrusted model, when we want to use your own class loader to load the class
At the time, you must not put the class into the classpath, otherwise, the loading of the class will be completed by other parental class loaders entrusted.
7. Hot deployment
Thermal deployment refers to a little change that redeps the class without closing the virtual machine.
Public interface point {
Public void emit ();
}
Public Class PointImpl Implements Point {
Public void emit () {
System.out.println ("IMPL 1");
}
}
Import java.net. *; public class pointserver {
Private ClassLoader Loader;
PRIVATE CL;
Public Point GetPoint (Object O) throws exception {
IF (o == NULL)
Reload ();
Point P = (Point) cl.newinstance ();
Return P;
}
Public void reload () throws exception {
URL [] URLS = New URL [] {new url ("file: sub /")};
Loader = New UrlclassLoader (URLS);
CL = loadinger.loadClass ("PointImpl");
}
}
Import java.io. *;
Public class pointclient {
Public static point pt;
Public static void main (string [] args) throws exception {
PointServer Server = New PointServer ();
BufferedReader Br = New BufferedReader (NEW INPUTSTREADER (System.in);
Pt = Server.getPoint (null);
System.out.println (Pt);
While (true) {
System.out.println ("EXIT, EMIT, RELOAD");
String cmd = br.readline ();
IF (cmd.equals ("exit")) {
Return;
} else IF (cmd.equals ("emit")) {
Pt.emit ();
} else IF (cmd.equals ("reload")) {
Server.Reload ();
Pt = Server.getPoint (PT);
System.out.println (Pt);
}
}
}
}
run:
Setting: classpath = .;
Point, PointServer and PointClient are in the same directory, PointImpl places in the next layer.
Output: PointImpl @ 3e
25A5
EXIT, Emit, Reload
Emit
IMPL 1
EXIT, EMIT, RELOAD (Modify the implementation of the Emit () method in PointIMPL, and reload)
Reload
PointImpl @ 42e816
EXIT, Emit, Reload
Emit
IMPL 2
EXIT, Emit, Reload
exit
Description: In order to make PointClient to use different versions of PointImpl, we cannot be defined as defined by the type of PT.
The PointImpl class, because this will trigger implicit loading so that the PointClient's class loader loads PointImpl, from
The new PointImpl version cannot be loaded by the consistency rule.
8. Using hot deployment
When using hot deployment in your own application, pay attention to the following:
a) The client can never reference the type of dynamic replacement, otherwise, one of the two consequences: The client will use the class loader implicitly loaded class (class unloaded case), or not load class (class has Loaded). b) The client cannot use a reference to the type of implementation, you must use a base class or an interface type.
c) Implementation classes must find the same version of the base class interface that is used to find the customer program. In other words, the implementation of the type of loader must be commissioned to the client's class loader. (Because PoingClient and Point are loaded by the system class loader, when the URLClassLoader is loaded, when the new PointIMPL is loaded, because he implemented the Point interface, it is necessary to verify that PointImpl is effective. Load Point, and due to the entrusted rules, this will have the URLClassLoad's parent class loader, that is, the system class loader is completed, because Point has already been loaded by the system class loader, so this can be successful.)
9. Boot path, extended path, class path
Booter loader loads the kernel system package from the bootclasspath, the extended class loader loads the extension of the kernel API from the extended path, and the system class loader loads the application code from the class path.
Delegate
Delegate
Booter loader
Extended loader
System class loader
Kernel APIS (such as RT.jar)
Java.lang
Java.io et al
Default expansion (such as JRE / lib / ext)
Class route class
Nick.ui, etc.
load
load
load
10. Class path
Settings Explanations - JAR Options Only list of single JAR-CP options List JAR and directory ClassPath environment variables are not recommended to use the current directory is not recommended
If the CLASSPATH environment variable is set, there may always be another application or user reset it to point to other locations. Similarly, it is impossible to rely on implicitly used current directory, if any participant on the system sets ClassPath, the current directory will be ignored.
11. Expansion path
Put the class in the extended path and the placement of the class path. mainly reflects in
a) It is easy to specify a large number of JAR files at once.
b) Extensions can be checked by all security checks.
Set the java.ext.dirs attribute overwritten the default settings, such as:
Java -djava.ext.dirs = mypackage1; mypackage2 mymainclass
Will use mypackage1 and mypackage2 as the extension path.
12. Boot path
The lead-loader has two significant features different from all other types of loaders, both of which are related to security:
a) The class that leads the loader load is not validated; in other words, the virtual machine assumes that they are a good structure.
b) The class that boots the loader load does not have to be safely inspected; this is a subtle difference in the loading optional package loaded with the extended product loader; the program does not check the privileges of the boot class; but the optional package requirements have permission, However, the default authority has been installed.
Setting -XbootClassPath in the command line to modify the default boot class path, such as:
Java-xbootclasspath: nrt.jar mymainclass
NRT.jar will be used as the boot class.
13. Debugging the loading structure
We can use three strategies to load problems:
a) Adapted the application.
b) Use the -verbose: Class sign.
c) Change the kernel API
For the first method, it means that we can get a reference to a class-loaded loader loaded by xx.class.getClassLoader (), and then get the entire delegate chain by recursively calling getParent (). ClassLoader Cl = xx.class.getClassLoader ();
While (cl! = null) {
System.out.println (CL);
CL = cl.getParent ();
}
For the second method, it is to increase a parameter when running a program via a Java command, thereby observing the output of the output.
Java -verbose: Class XX
For the third method, refers to the source code for modifying the kernel API, and then enables the replacement of the kernel API code by increasing the standby boot class path. The modified kernel API is placed in a Somewhere directory.
Java-xbootclasspath / p: Somewhere XX
14. Inverted Problem and Context Class Loader
According to the visibility rules, if the loader of class A is the subclass of the loader of class B. Then class A can see all the classes loaded by the loader of class B, but in contrast, class b does not see the class loaded by class A.
Not caused by legal replacement
The relationship between class A and class B is effective class loader relationship. Uncommonless arbitrary A contains the B type field / variable CLA equal to / source from CLBA extended BCLA equal to / from CLBA, B-class reference CLA equal to CLB
Note: A source from B means B is a parent class loader.
Causes an inversion reference: When classes in the extension path need to reference classes in class paths. E.g:
PUBLIC CLASS POINTSERVER {
Public Static Point getPoint (String ClassName) throws exception {
Class C = Class.Forname (ClassName);
Return (Point) c.newinstance ();
}
}
Public class poingclient {
Public static void main () THROWS Exception {
Point P = PointServer.getPoint ("PointImpl");
}
}
In the above code, suppose we put the PointServer in the extended path, and put the PointClient and PointImpl in the class path, then when the PointClient calls the getPoint () method, the class.forname () method among the PointServer will be loaded. Class, because this method uses the PointServer class-loader (expanded "loader) to load the PointImpl class, thereby causing the generation of an inverted problem.
In order to solve this problem, a method is that we can pass the load-loadClient's class loader when calling getPoint (), and then load it when the PointServer loads the class. However, this method will look very cumbersome and troubles if Client and Server have ordinary interactions. The second method is to use the context-based loader, the context-based loader is located in the current thread. The modified version is like this.
PUBLIC CLASS POINTSERVER {
Public Static Point getPoint (String ClassName) throws exception {
ClassLoader Cl = Thread.currentthread (). GetContextClassLoader ();
Class C = Class.Forname (ClassName, True, Cl); Return (Point) C.NewInstance ();
}
}
Public class pointclient {
Public static void main () THROWS Exception {
ClassLoader Cl = PointClient.class.getClassLoader ();
Thread.currentthread (). SetContextClassLoader (CL);
Point P = PointServer.getPoint ("PointImpl");
}
}
15. Metadata, that is, the data describing the binary structure, most of the metadata is type information, listing the base class, hypertext, fields, and methods. Type information makes the dynamic link dynamic links more reliable by verifying a common class view that communicates with the client and server sharing in the runtime.
16. Binary category
17. Reflection field
The Java language is characterized by the Field class. To get a field of the class, we can call getfields () () and getDeclaredfields () on the Class. The difference between these two methods is that getfields () can return all fields to the base class, but he can only return to public modified fields. getDeclaredFields () only returns the fields of the current class, and is all the fields in the class, including private, protected, public, and more. We can also get a particular field by specifying a field name. After getting a reference to the field, we can call getType (), getName (), getName (), getModifiers (), etc. on the field to further get detailed information. E.g:
Public class example2 {
Public int E;
}
Public class example extends example {
Private int A;
protected int b;
Public INT C;
INT D;
}
Public class exampleExplorer {
Public static void main (string [] args) throws exception {
Class C = Class.Forname ("eXample");
Field [] fs = c.getDeclaredfields ();
FOR (Field F: FS) {
Emitfield (f);
}
System.out.println ("==============");
FS = C.Getfields ();
FOR (Field F: FS) {
Emitfield (f);
}
}
Public Static Void Emitfield (Field F) {
Switch (f.getmodifiers ()) {
Case modifier.public:
System.out.print ("public");
Break;
Case Modifier.private:
System.out.print ("private");
Break;
Case Modifier.protace:
System.out.print ("protected");
Break;
}
System.out.println (f.gettype () " f.getname () "; ");
}
}
Output: Private Int A;
protected int b;
Public INT C;
INT D;
============
Public INT C;
Public int E;
18. Reflection method:
The Java language is classified by the Method class. To get a class method, we can call getMethods () () and getDeclaredMethods (), etc. on the Class. The difference between the two methods is similar to the field. Of course, we can also obtain a particular method by specifying the method name, but because the method is allowed to be overloaded, we need to pass the type of variable in addition to the transfer method name. For reference types, we can get into their .class field, for example, for String type, we can pass String.class. For basic types we can pass to the .type field of them, for example, for int types, we can pass Integer.Type, and for Integer types, we can pass Integer.class. After obtaining the reference to Method, we can call getName (), getModifiers (), getreturntype (), etc. to get information information.
19. Reflection call:
Reflecting the API to report the fields, methods, and constructors of the class, while the call part of the reflection API uses the status of the Field, Method, the Constructor class in runtime, and modifies the status of the class (and instance), including the value of instantiation, modification, and getting fields. Methods of calling classes or instances. It should be noted here that when the fields and methods of the class and instances are taken to treat. When we operate on the fields and methods of the instance, we need to pass a reference to an instance, which is in general, the THIS reference that is implicitly incomplete. And when you perform operations on the fields and methods, we only need to pass NULL. E.g:
Field operation:
Public class example {
Private int A;
PRIVATE STRING B;
}
Public class exampleExplorer {
Public static void main (string [] args) throws exception {
Class C = Class.Forname ("eXample");
Object o = c.newinstance ();
Field Fa = C.GetDeclaredField ("a");
Field FB = C.GetDeclaredField ("B");
Fa.setAccessible (TRUE);
Fb.setAccessible (TRUE);
Fa.setint (O, 1);
INT a = fa.getint (o);
Fb.set (O, "Hello World");
String b = (string) fb.get (o);
System.out.println ("A's Value IS" A "B's Value IS" B);
}
}
Output: a's value is 1 b's value is hello world
Note: Under normal circumstances, we cannot operate the private fields of the class. Use the reflection is no exception, but sometimes, if you want to serialize, we must have the ability to deal with these fields, this time we will You need to call the setaccessible () method on AccessibleObject to allow this access, and due to the Field, Method, and Constructors in the reflection class inherited from AccessibleObject, we can implement these fields by adjusting the setaccessible () method on these classes. operating. But sometimes this will become a security hidden danger. To do this, we can enable Java.Security.Manager to determine if the program has permission to call setAccessible (). By default, the code for the kernel API and extended directory has this permission, and the class path or the application loaded by URLClassLoad does not have this permission. For example: When we perform the above programs in this way> Java -Djava.security.Manager ExampleExplorer
Exception in thread "main" java.security.accessControlException: Access Denied (
Java.lang.Reflect.reflectpermission supports
At java.security.accessControlContext.checkpermission (Unknown Source)
...
Method Operation:
Public class example {
Public void a () {
System.out.println ("Method A");
}
Public static void b () {
System.out.println ("Method B");
}
}
Public class exampleExplorer {
Public static void main (string [] args) throws exception {
Class C = Class.Forname ("eXample");
Object o = c.newinstance ();
Method M = C.getMethod ("a");
M.INVoke (O);
m = c.getMethod ("b");
M.INVoke (NULL);
}
}
Output: Method a
Method B
20. Modify Final fields with reflection
We can modify the Private field to modify the final field, which is different from the reflection, but is different from private, for the Final field, the compiler generally embeds him in the code, so if only the definition is modified only by reflection Value, and not modified the subsequent reference value, will not truly reach the target of the final field. This method of modifying the final field by reflection is now canceled by Sun, so there is no effective way to modify the Final field.
21. Reflection and call triggers
When reflecting the method, there may be three exceptions that may be thrown:
a) Throw unspecified exception: such as Error or RuntimeException, such exceptions will continue to be abandoned through the reflective layer.
b) The test error of the declaration: Since the corresponding method signature may not be known when writing reflection code, it is impossible to capture the corresponding capture through the try-catch block, for this, if this is thrown in the actual call When class is exception, VM will put them into invocationTargeTexception, we can capture this exception in places where reflections, then get the actual exception, re-throw. c) Throwing an unspected test error: This kind of situation is rarely seen, because if the class throws an unlessned abnormality, it will not be able to compile, the reason that may be caused by local recompilation, not Match or damaged binary classes, such exceptions will be packaged as undeclaredthrowedException.
22. Dynamic Agent
When using the reflection call, the client program uses the general purpose API to call the method (in the server class) when compiling. When using a dynamic agent, the server uses the general API to implement the method on the server class, and the purpose is to meet the specification of the customer program. For example, suppose we have three interfaces A, B, C, sometimes, we need a certain type of implementation A, B interface, sometimes, we need a certain implementation class to implement A, C interface ... This, in order to achieve us Target, we may have 2 3 times to implement classes. In order to solve this problem, we introduce a dynamic agent. In the dynamic agent, we mainly need two classes, proxy and invocationhandler, where the most important thing here is the Proxy's newProxyInstance () method. E.g:
Public class logginghandler imports invocationhandler {
Public Object Invoke (Object Proxy, Method Method, Object [] ARGS)
Throws throwable {
IF (Method.getName (). Equals ("toString")) {
Return super.toString ();
}
System.out.println ("Method" Method "Called On" Proxy);
Return NULL;
}
}
Public class loggingdemo {
Public static void main (string [] args) throws exception {
ClassLoader Cl = LoggingDemo.class.getClassLoader ();
DataOutput D = (DataOutput) proxy.newproxyinstance (Cl,
New class [] {dataoutput.class}, new logginghandler ());
D.WriteChar ('a');
D. Writeutf ("Hello World");
}
}
Output:
Method public abstract void java.io.DataOutput.writechar (int) throws java.io.ioException
Called on t3.logginghandler@a90653
Method public abstract void java.io.DataOutput.writeutf (java.lang.string) throwsjava.io.ioException caled on t3.logginghandler@a90653
Note: From the above-mentioned operation, we can see that all the calls to D are actually forwarded to the loggingHandler.
Through proxy.newproxyinstance (), we have established the proxy we need, this method has three parameters, the first is type
The carrier is used to load the Class array specified by the second parameter. The second parameter is the list of interfaces, that is, the object column to be proxy
Table, for example, if we need to support interfaces A, B, you can fill in A.CLASS and B.CLASS here. Through this interface list,
In the newly generated agent, the methods on interfaces A and B can simultaneously support. The third parameter is a dynamic agent class, he only needs to be realized.
Invoke () method When a method is called on the agent, this method call will be transferred to the INVOKE () method of this agent.
It should be noted here that in InvokeHandler implementation of the class, for methods from Object (), havehcode ()
And equals (), we must forward them to Super's handler, otherwise the stack overflow will be overflow.
23. Realize the forwarding process of dynamic agent
In order to simulate any interface, dynamic proxy needs to understand the semantics of the interface, or need to forward method calls to other objects that understand semantics. Because the agent is for versatility, it is not necessary to understand the specific features of the interface, and most dynamic agents generally forward call to other objects.
The dynamic agent's role is reflected in the method call forwarding, the dynamic agent can intercept the method call, analyze, or modify the parameters, passed the call to other objects, analyze, or modify the results, and return this result to the call. If you are properly configured, dynamic agent can be transparent, and information is not required for client programs or server code. E.g:
Public class logginghandler imports invocationhandler {
Private DataOutputstream OS;
Public loggingHandler (DataOutputstream OS) {
THIS.OS = OS;
}
Public Object Invoke (Object Proxy, Method Method, Object [] ARGS)
Throws throwable {
IF (Method.getName (). Equals ("toString")) {
Return super.toString ();
}
System.out.println ("Method" Method "Called On" Proxy);
Method.invoke (OS, ARGS);
SYSTEM.OUT.PRINTLN ();
Return NULL;
}
}
Public class loggingdemo {
Public static void main (string [] args) throws exception {
ClassLoader Cl = LoggingDemo.class.getClassLoader ();
DataOutput D = (DataOutput) proxy.newproxyinstance (Cl,
New class [] {dataoutput.class}, new logginghandler (new dataputstream (system.out));
D.WriteChar ('a');
D. Writeutf ("Hello World");
}
}
Output:
Method public abstract void java.io.DataOutput.writechar (int) throws
Java.io.IOException Called on T3.LoggingHandler@a90653
a
Method public abstract void java.io.DataOutput.writeutf (java.lang.string) Throws
Java.io.IOException Called on T3.LoggingHandler@a90653
Hello World
Description: We now forward the client's request to other objects (OS).
24. Handling an exception in InvocationHandler
Since we are using reflection, forward the request to other objects, so we can put the call into a try-cathc block in the previous way and capture the InvocationTargeTexception. This approach has another advantage that since the server is now directly called directly, it can be processed by the agent, so it can be processed at the agent at first level, without spreading to the client.
25. Customize metadata
Through the metadata in the existing class file, we can call a class method to modify his a field, but these metadata is not enough. The above metadata does not include the following two: value parameters, and the status conversion table allowed by the interface. The correct unit of the numerical parameters refers to the assumption that we have a method in an interface now, and although we can accurately locate this method by reflection, all existing metadata does not accurately point out In order to call this method, the unit of parameters should be rising or milliliters. For the second state conversion table refers to, if there are two methods A () and B (), and the A () method should be called before B (), this relationship is not expressed in metadata. of. To solve this problem, J2SE 5.0 introduces an ANNOTATION class, which provides a method for users to add custom metadata.
26. Serialization processing and metadata
In serialization, metadata plays two key functions. First, serialization relies on class metadata and reflection to extract instance status. The second role of metadata is to ensure that the recipient gets the correct class through the flow.
27. Serialization basics
If the reflection access can handle any fields of any object, there is no prevention of language designers from making all kinds of serialized restrictions. But this is not the case, there are two points. First, some examples of instances contain local resources of VM, process, or computer. These classes include threads, files, sockets, and database connections. Now, there is no better way to re-instantize an object based on the status of these resources. The second reason is related to security. Some classes pay attention to private fields of private fields. However, serialization provides the back door. By the back door, the field can be written to the serialization stream, analyze the flow content, thereby accessing these fields. In the Java language, developers do not require the developers to consider these issues for each class, but believe that the object is not serialized by default.
28. Some fields of serialization ignored
There are three situations, and serialization does not necessarily read all fields and write their stream: a) Only the base class itself can be serialized before processing the base class field.
b) Serialization ignore static fields because static fields are not part of any special instance status.
c) Use the Transient keyword to disable serialization of a particular field.
Public class person {
Public String Name;
Public persons () {
}
Public Person (String Name) {
THIS.NAME = Name;
}
Public string getname () {
Return Name;
}
Public void setname (String name) {
THIS.NAME = Name;
}
}
Public Class Man Extends Person IMPLEments SerializAble {
Private string agec;
Public static int count;
Public Transient string country;
Public Man (String Name) {
Super (Name);
}
Public static int getCount () {
Return count;
}
Public static void setcount (int count) {
Man.count = count;
}
Public string getage () {
Return Age;
}
Public void setage (String age) {
THIS.AGE = AGE;
}
Public string getCountry () {
Return country;
}
Public void setCountry (String country) {
THIS.COUNTRY = Country;
}
Public string toString () {
Return "Name:" Name "Age:" AGE "Country:" Country
"Count:" count;
}
}
Public class serdemo {
Public static void main (string [] args) throws exception {
MAN M = New Man ("Nick");
M.SETAGE ("25");
M.SetCountry ("
China ");
Man.count = 1;
ObjectOutputStream Oos = New ObjectOutputStream (New FileoutputStream
"p.txt"));
Oos.writeObject (m);
OOS.FLUSH ();
OOS.Close ();
}
}
Public class deserdemo {
Public static void main (string [] args) throws exception {
ObjectInputStream OIS = New ObjectInputStream (New FileInputStream
"p.txt"));
MAN M = (man) Ois.ReadObject ();
System.out.println (m);
}
}
Output: Name: Null Age: 25 Country: null count: 0
Description: Because the Name field is a field belonging to the base class (Person), Person is not declared as serialization, so it is ignored in the serialization process, and only the default value of this field is in the reverse train. NULL. Because Country is the Transient field, Count is a Static field, so it is also ignored. There is only default values after the reverse train.
29. Serialization and class constructor
If a class is marked as serializable, then any untrusable base class of the class must have a default constructor.
Public class person {
Public persons () {
System.out.println ("Person Constructor.");
}
}
Public Class Man Extends Person IMPLEments SerializAble {
Public man () {
System.out.println ("Man Constructor.");
}
}
Output: Person Constructionor.
Explanation: When the anti-sequence-of-sequence MAN is performed, the system only calls the constructor of the Person and does not call the constructor of the Man. because,
The serialization plan is assigned to the field in the stream, and the constructor running Man is more than.
30. Using ReadObject and WriteObject
ObjectInputStream uses reflection to check the readObject () method before the state of the stream read object. If ObjectInputStream only calls readObject () without performing normal counter serialization.
Public Class Man Extends Person IMPLEments SerializAble {
Public static int count;
Public man () {
count = 1;
}
Private Void ReadObject (ObjectInputStream Ois) throws oException,
ClassNotFoundException {
Ois.defaultReadObject ();
Man.count = 1;
}
}
Public class deserdemo {
Public static void main (string [] args) throws exception {
ObjectInputStream OIS = New ObjectInputStream (New FileInputStream
"p.txt"));
MAN M = (man) Ois.ReadObject ();
System.out.println ("M's Count Is" man.count);
}
}
Output: M'S Count Is 1
Explanation: When implementing readObject (), it is generally necessary to implement two things: First, callback ObjectInputstream
The defaultreadObject () method reads fields according to normal serialization; the other is to perform any ready to add back serialization
Custom step of the process. From the above discussion, it knows that during the anti-series process, the serial constructor is not executed.
But we can perform the necessary initialization work by implementing the readObject () method, for example, initializing the serialization
The static fields and transient fields that are ignored in the process.
31. SerialVersionuid
When rendering, the VM needs to check whether the category in the stream is consistent, which is implemented by adding a SerialVersionUID in the stream. By comparing the ID values in the flow and the class, the VM can know if the appropriate class is loaded. We can also explicitly assign the value of this field, so that this consistency check can be avoided. Public Class Man Implements Serializable {
Private static final long service =
1L;
Public int count;
Public man () {
count = 1;
}
}
Public Class Man Implements Serializable {
Private static final long service =
1L;
Public man () {}
}
Description: We use the first MAN class before serialization, use the second MAN class when deserialization, in general, this will result in exception, but because we explicitly assign the serialversionUid field, Will not throw an exception.
32. Compatible and incompatible changes
Once SerialVersionuid is set, the programmer is required to ensure the new and old version of the class.
Change Type Example Compatibility Change Add / Remove WriteObject () / ReadObject (); Add / Remove WriteObject () / ReadObject (); Add Serializable; Change Access Demon; Delete Static / Transient Included from the field; move the class in the hierarchy ; add a field static / transient; change basic types; switching Serializable / Externalizable, delete Serializable / Externalizable, change writeObject () / readObject () whether to process the default field data set; add generated with the old version is not compatible with the object writeReplace or readResolbe
33. Explicitly manage the schizomeric field
In addition to the above method, we can use ObjectInputStream.getField to explicitly manage how to drag out the field from the stream, while using ObjectOutputStream.putField to explicit the field into the stream.
Public Class Man Implements Serializable {
PRIVATE STRING NAME;
Public string getname () {
Return Name;
}
Public void setname (String name) {
THIS.NAME = Name;
}
Private void writeObject (ObjectOutputstream OOS) throws oException {
ObjectOutputStream.putfield pf = Oos.putfields ();
PF.PUT ("Name", "cen");
Oos.writefields ();
}
}
Public class serdemo {
Public static void main (string [] args) throws exception {
MAN m = new man ();
M.setname ("Nick");
ObjectOutputStream Oos = New ObjectOutputStream (New FileoutputStream
"p.txt"));
Oos.writeObject (m);
}
}
Public class deserdemo {
Public static void main (string [] args) throws exception {
ObjectInputStream OIS = New ObjectInputStream (New FileInputStream
"p.txt"));
MAN M = (man) Ois.ReadObject ();
System.out.println ("M's Name IS" M.GetName ());
}
}
Output: M's Name is Cen
Description: We can bypass the original reflex mechanisms through ObjectOutputStream.putfield, and serialize the needs
Fields and field values are customized.
34. Rewrived the data
In the above example, we only write only the defined fields in the class when WriteObject, because the class defined field will be written as metadata, and then the system passes the reflex mechanism Can successfully execute it. The following demonstrates how to write a field that is not defined when serialization.
Public Class Man Implements Serializable {
Private static firm ObjectStreamfield [] SerialPersistentFields = {
New ObjectStreamfield ("Name", String.class,
New ObjectStreamfield ("age", integer.type)};
Private Void ReadObject (ObjectInputStream Ois) throws oException,
ClassNotFoundException {
ObjectInputStream.getfield gf = ois.readfields ();
String name = (string) GF.Get ("name", null);
INT AGE = GF.GET ("age", 0);
System.out.println (Name "IS" AGE "Years Old.");
}
Private void writeObject (ObjectOutputstream OOS) throws oException {
ObjectOutputStream.putfield pf = Oos.putfields ();
PF.PUT ("Name", "cen");
PF.PUT ("Age", 25);
Oos.writefields ();
}
}
Output: cen is 25 years old.
Description: If there is no defined field in the stream, then we need to add meta information for this part of the field, which is mainly
Includes an array of serialPersistentFields. And write this section and fields in WriteObject ()
value. Correspondingly, in the RaedObject (), we also need to manually extract this part of the value.
35. Deactivate metadata
Serialization mechanisms also provide several ways to allow metadata to be transmitted. This includes adding data after defaultWriteObject () to enable object externalization, and completely replace the defaultWriteObject () method.
36. Add data after defaultWriteObject ()
Since ObjectInputStream and ObjectOutputStream respectively implements DataInput and DataOutput interfaces, these interfaces provide assistance methods for read and write basic types, so we can use these methods to write custom data. Public Class Man Implements Serializable {
Private Void ReadObject (ObjectInputStream Ois) throws oException,
ClassNotFoundException {
Ois.defaultReadObject ();
String name = ois.readUTF ();
Int agth = ois.readint ();
System.out.println (Name "IS" AGE "Years Old.");
}
Private void writeObject (ObjectOutputstream OOS) throws oException {
Oos.defaultwriteObject ();
Oos.WriteUTF ("cen");
Oos.WriteInt (25);
}
}
Output: cen is 25 years old.
Description: With the auxiliary method provided by DataInput and DataOutput, we can easily add a custom field. This
There are a few things to note that first is the write and reading of the custom field, must be after the defaultxxObject () operation.
The second is that since the custom data is not metadata, the user who uses different types of versions cannot determine the custom field in the stream.
Meaning, this is prone to flexibility compared to the previous method using SerialPersistentFields.
37. Externalization
Externalizable extends serializable, when implementing Externalizable, programmers must transfer data for such class and transfer data for any base class.
Public class man imports externalizable {
Public man () {
System.out.println ("Man's Constructor");
}
Public void readexternal (ObjectInput in) throws oException {
String name = in.readutf ();
INT AGE = in.readint ();
System.out.println (Name "IS" AGE "Years Old.");
}
Public void writeexternal (ObjectOutput out) throws oews {
Out.writeutf ("cen");
Out.writeint (25);
}
}
Output: Man's Constructionor
Cen is 25 years old.
Description: From the output we can see that the constructor will be called when implemented by externalization. So when we
When you need to use an external mechanism, you need to pay attention to the following points: the processing itself and all fields of the base class; because
Writeexternal () method must declare that the WriteExternal () method may be called at any time as public, malicious or wrong.
Bring any of some states into an object; the Externalizable class must have a public constructor; do not write into the metadata, only write the actual value of the field.
38. WriteObject is only written to the original data
This method refers to writing custom data directly using DEFAULTWRITEOBJECT () when implementing WriteObject ().
39. Comparison of three methods:
These three methods of ignoring metadata are "adding data after defaultWriteObject ()" because this makes the serial stream of streams a strange mix; difference is "using externalization", because this will All advantages of metadata; the worst is: "WriteObject is only written to raw data", because this is a violation of the normative purpose, and ordinary tools cannot read data from the stream.
40. Object replacement
Object flow and object itself can perform object replacement when serialization. Object replacement features have multiple usages. If the object map contains a non-serialized object, you can replace the serialized object. If you are writing a distributed program, you can use the object's placement program (stub) to replace the status of the object, so that the recipient gets a reference to the remote object, not a local copy of the object.
41. Flow control replacement
In order to replace objects, we need to re-implement ObjectOutputStream, and call EnableRePlaceObject (TRUE) to allow enable object replacement functions and implement specific replacement works in the ReplaceObject () method. For ObjectInputStream, we need to call EnableResolveObject (TRUE) and implement the resolvePePject () method.
Public class man {
PRIVATE STRING NAME;
Public man () {}
Public string getname () {
Return Name;
}
Public void setname (String name) {
THIS.NAME = Name;
}
}
Public Class Serman Implements Serializable {
PRIVATE STRING NAME;
Public serman (man m) {
this.name = m.getname ();
}
Public string getname () {
Return Name;
}
Public void setname (String name) {
THIS.NAME = Name;
}
}
Public class outputreplacer extends ObjectOutputStream {
Public OutputReplacer (OutputStream OO) Throws oException {
Super (OO);
EnableReplaceObject (TRUE);
}
Protected Object ReplaceObject (Object Obj) throws oException {
IF (Obj InstanceOf Man) {
System.out.println ("here");
Serman SM = New Serman ((Man) OBJ);
Return SM;
}
Return Super.ReplaceObject (OBJ);
}
}
Public Class InputReplace EXTENDS ObjectInputStream {
Public InputReplacer (InputStream IS) Throws oException {
Super (IS);
EnableResolveObject (TRUE);
}
Protected Object ResolveObject (Object Obj) throws oException {
IF (Obj InstanceOf Serman) {
System.out.println ("there");
MAN m = new man ();
M.setname ((serman). GetName ());
Return M;
}
Return Super.ResolveObject (obj);
}
}
Public class serdemo {
Public static void main (string [] args) throws exception {
MAN m = new man ();
M.setname ("Nick");
ObjectOutputStream Oos = New OutputReplacer (New FileoutputStream
"p.txt"));
Oos.writeObject (m);
}
}
Public class deserdemo {
Public static void main (string [] args) throws exception {
ObjectInputStream OIS = New FileInputStream ("p.txt");
MAN M = (man) Ois.ReadObject ();
System.out.println (M.GetName ());
}
}
Output: NICK
Description: Since the MAN class cannot be serialized, we need to use a servatic Serman class to replace him.
change. By introducing an alternative mechanism, we can filter the class that needs to be serialized, or for a field of the class.
filter.
42. Class Control Replacement
Classes can be replaced by implementing WriteReplacing () and ReadResolve () methods. The difference between his and stream control is that the class level replace can be used only when accessing the source code that is replaced. The class uses the class level replacement mechanism, and its serialization form is separated from the memory representation. If the class contains complex serialization code, explicitly written separate serialization code may have more effect. For design (such as Singleton mode), depending on the anti-selecente behavior is similar to the public constructor, sequentialization may undermine the design of Singleton.
Public Class Man Implements Serializable {
PRIVATE STRING NAME;
Private static man m = new man ("nick");
Private man (String name) {
THIS.NAME = Name;
}
Public static man getman () {
Return M;
}
Public string getname () {
Return Name;
}
Public void setname (String name) {
THIS.NAME = Name;
}
}
Public class deserdemo {
Public static void main (string [] args) throws exception {
ObjectInputStream OIS = New ObjectInputStream (New FileInputStream
"p.txt"));
Man m1 = (man) Ois.ReadObject (); OIS = New ObjectInputStream (New FileInputStream ("p.txt");
MAN M2 = (man) Ois.ReadObject ();
System.out.println ("M1's Name IS" m1.getName ());
System.out.println ("M2's Name IS" M2.GetName ());
System.out.println ("M1 == M2 IS" (M1 == M2));
}
}
Output: m1's name is nick
M2's name is nick
M1 == m2 is false
Explanation: Through the above output, we can see that by reverse sequencing, we have destroyed the original Singleton design.
Modify the MAN class and increase the implementation of Readresolve ():
Public Class Man Implements Serializable {
...
Private Object Readresolve () throws oException {
IF (Name.Equals ("Nick"))
Return M;
Else
Throw New InvalidObjectException ("NO Man Call";
}
}
Output: m1's name is nick
M2's name is nick
M1 == m2 is true
Explanation: Through this output, we can see that the original design has not changed even after the reverse selecule. for
ReadResolve () method, he is called after the reverse sequence, that is, the reverse sequence first creates a new instance, and then calls it.
ReadResolve () method, if the returned value is not a new instance, this new instance will be reclaimed.
43. Replacement rules
Object replacement contains the following sort rules:
a) Class level replacement is called before the flow level replacement. Class level explanation appears before the stream level explanation.
b) The class level replacement is recursive, and the class level explains not recursively executed.
c) Flow level replacement does not reclaim. There is only one chance to explain the object once.
d) Replace the object during serialization. The object is replaced after the object is completely constructed during the reverse series of steps.
Here, the second and fourth rules are non-symmetrical, which gives very much troubles to recursively use readResolve () and WriteReplace (), so if there is no special case, do not use the recursive way.
44. Java2 security
Public class destruct {
Public static void main (String [] args) {
Try {
FILE F = New File ("a.txt");
System.out.println ("DELETE FILE?" F.delete ());
} catch (exception e) {
E.PrintStackTrace ();
}
}
}
a) Operate directly:
i. Command line: Java Destruct
II. Output: DELETE FILE? TRUE
Iii. Description: When we run the program directly, the file is successfully deleted.
b) Increase security options:
i. Command line: java -djava.security.manager destruct
II. Output:
Java.security.accessControlXception: Access Denied
(java.util.propertypermission user.dir ie)
At java.security.accessControlContext.checkpermission (Unknown Source)
AT java.security.accessController.checkpermission (unknown source)
...
At t5.destruct.main (Destruct.java: 22)
III. Description: When we add a security option, the Security Manager will check the permissions of the program, and because the general application has only the minimum permissions, he cannot delete the file.
c) Add policy files:
i. Command line: java -djava.security.manager -djava.security.policy = destruct.policy destruct
II. Output:
DELETE FILE? TRUE
Iii. Description: By introducing a policy file, we can define the programs permission. Thereby modify the default behavior.
IV. Policy file:
Grant {
Permission java.io.filepermission "<< All Files >>", "Read, Write, Delete";
}
45. Customized class loader
We can implement custom class loading behaviors by extending existing class loaders. In general, we should only rewrite the FindClass () method.
Public interface IResourceTransformer {
Public Byte [] TransformClassBytes (Byte [] inout, int LEN;
Public Url TransformResourceURL (URL Resource);
Public Enumeration TransformResources (Enumeration Resources);
}
Public Class ResourceTransformerAdapter Implements IRESOURCETRANSFORMER {
Public Byte [] TransformClassBytes (Byte [] inout, int start, int LEN) {
Return NULL;
}
Public Enumeration TransformResources (Enumeration Resources) {
Return NULL;
}
Public url transformResourceURL (URL Resource) {
Return NULL;
}
}
Public class classnotter extends resourceetransformeradapter {
Public Byte [] TransformClassBytes (Byte [] inout, int start, int LEN) {int end = start g
For (int i = start; i INOUT [i] = (byte) ~ inout [i]; } Return INOUT; } } Public Class TransformClassLoader Extends UrlclassLoader { Private IResourceTransformer RT; Public TransformClassLoader (URL [] URLS, IRESOURCETRANSFORMER RT) { Super (URLs); THIS.RT = rt; } Private url geturlbase (URL URL) { URL [] URLS = getURLS (); For (URL U: URLS) { IF (url.toExternalform (). StartSwith (u.toExternalform ())))))) Return U; } Return NULL; } Protected class > Findclass (String name) throws classnotfoundexception { System.out.println ("My FindClass"); String classname = name.Replace (".", "/") ".Class"; URL URL = Super.getResource (ClassName); IF (URL == Null) { Return NULL; } URL URLBASE = GETURLBASE (URL); IF (urlbase == null) Throw New Error ("URL HAS NO BASE"); InputStream IS = NULL; Try { IS = url.openstream (); IF (IS == NULL) Return NULL; BYTEARRAYOUTPUTSTREAM baos = new byteArrayoutputStream (); For (int CH = 0; (= (is.read ())))))))))! = -1;) { Baos.write (CH); } BYTE [] classbytes = baos.tobyteaRray (); Rt.TransformClassBytes (Classbytes, 0, Classbytes.Length); Return DefineClass (Name, Classbytes, 0, Classbytes.Length, New Codesource (Urlbase, New Certificate [0])); } catch (ioexception ie) { IoE.PrintStackTrace (); } Return NULL; } } Public class tCLDEMO { Public static void main (String [] args) { Try { URL URL1 = New URL ("File: / E: / Java / Study / java% 20component /"); UrlclassLoader Cl = New TransformClassLoader (New URL [] {URL1}, New classnotter ()); System.out.Println (CL); Class C1 = Class.Forname ("TEST", TRUE, CL); System.out.println (C1); } catch (exception e) { E.PrintStackTrace (); } } } Output: t5.transformClassLoader @ 1A46E30 My FindClass Exception in thread "main" java.lang.classformaterror: incompatible magic Value 889275713 in Class File Test At java.lang.classloader.defineclass1 (Native Method) AT java.lang.classloader.defineclass (unknown source) ... At t5.tcldemo.main (tCLDEMO.JAVA: 27) Note: Due to the default, VM will use the default loading policy to load the class we need to load. Therefore, we need To put the test.class in a loader, you cannot load the location, and then the VM will call the FindClass () method to find class. Since we use ClassNotTER to reverse the binary code, the system will throw a ClassFormaterror. 46. Protocol handler As can be seen from the above example, what we need to do is to implement the FindClass () method for positioning of class files. To this end, we can use another method called a protocol handling program to solve this problem. The protocol handler divides the partition resource into the following different pieces: protocol handler (Handler) analysis of the URL, returns a connection; connection (connection) managing communication and return to stream; streaming write data, and possibly apply conversion. Here we define a new protocol called "Not" to demonstrate the application. a) Structure diagram: UrlstreamHandlerFactory UrlstreamHandler UrlConnection Returns the appropriate Handler based on the protocol type Returns the appropriate Handler based on the protocol type Strive to Connection specific details b) code: Public Class NoturlReader Implements UrlstreamHandlerFactory { Public urlstreamHandler CreateURLStreamHandler (String Protocol) { IF (Protocol.equals ("not")) { Return New NotHandler (); } Return NULL; } Public static void main (string [] args) throws exception { Url.SeturlStreamHandlerFactory (New NoturlReader ()); URL URL = New URL ("NOT: TEST.CLASS"); InputStream IS = url.openstream (); INT B; INT i = 0; While ((b = is.read ())! = -1) { System.out.printf ("% h / t", b); IF (i% 16 == 15) { SYSTEM.OUT.PRINTLN (); } i ; } } Public class nothandler extends urlstreamhandler { Protected UrlConnection OpenConnection (URL URL) THROWS IOEXCEPTION { Return New Notconnection (URL); } } Public Class Notconnection Extends UrlConnection { Private inputStream IS; Public Notconnection (URL URL) { Super (URL); } Public void connect () throws oException {} Public InputStream GetInputStream () throws oException { IF (is == null) { String file = getURL (). Getfile (); IS = new fileinputstream (file); } Return IS; } } c) Output: Ca Fe Ba Be 0 0 0 31 0 1e 1 0 4 54 65 73 74 7 0 1 1 0 10 6A 61 76 61 2F 6C 61 6e 67 2F 4F 62 6A 65 63 74 7 0 3 1 0 6 3C 69 6E 69 74 3e 1 0 3 28 29 56 1 0 4 43 6F 64 65 ... 47. Customize the choice between the loader and protocol handler The flow handler can be used to connect to any resource, but the custom class loader can only load the class and other collaborative locations. The flow handler utilizes the security feature that has been built into the URLClassLoader. Moreover, because they can be installed on the command line, the presence of the flow handler can be completely transparent to other code. The flow handler has only one disadvantage, that is, when trying to process the protocol format and HTTP has a completely different syntax. At this time we may need additional ParseurL () methods in Handler. 48. Reasons using geneting programming, GP) The reason for the use of generated programming is simple: achieving effective capture and reuse of issues domains. Domain analysis identifies the commonality and denaturation of the related software system series. The commonality is a standard feature written in the system and shares all sequences of the system. Vigification changes with different products and the same product. At some point in time in the system life, you must make a selection and designation specification for a variety of degeneration. Make the selected point in time becomes a binding time. 49. Classified by binding time In the traditional object-oriented design, the denaturation model is established by integrated inheritance and parameterization operation. In the inherited solution, instantiate each different specification is used as different specific classes. During development, the specification is bound, which is called compilation binding. Parameterization solutions Blend specification at runtime through incoming parameters. This means that if the program generates parameterized control, the end user can select a specification at runtime. There are four obvious binding times in the Java development field: when the compiler is running, the compile period binding; when the designer configures the initial state of the compiled component, the design is bound; if you install the component to the use of them When the network is deployed, the binding is displayed; after the application starts execution, the runtime binding occurs. 50. Reasons for generating code with Java l High quality type information is a very value implicit specification document. l Flexible class loading supports any combination of binding time and binding mode. l Java source files are easy to read and generate. l Java bytecode files are easy to read and generate. l The code generated can provide extremely performance to eliminate the overhead of the VM. 51. Classification of binding time and mode Static Binding Mode Dynamic Binding Mode Development Ide Wizard, RMIC, JavaBeans Default Serialization Design JavaBeans Deployment / Running JSP, EJBEJB, Dynamic Agent Input / Output Source File Class Binary Java Class Binary Data RMI Placener, IDE Wizard RMI Placbo, Dynamic Agent Non-Java Data SOAP Mixed Data JSP, EJBEJB