The JVM is a virtual machine and a specification, and he follows the design principles of the von Neumann architecture. Von Neumann architecture, it is pointed out that the computer processing data and instructions are binary number, using stored procedures to store in the same memory without distinction, and sequential execution, instruction by the operation code and address code, the operation code determines the type of operation and the number of operations of the numeric type, the address code indicates the address code and the operand. From DOS to Window8, Unix to Ubuntu and CentOS, Mac OS, and so on, different operating system instruction sets and data structures differ, and the JVM creates a unified set of data structures and operations instructions that are defined by the virtual machines on the operating system. Translating the same set of languages into major mainstream operating systems enables cross-platform operation, which can be said that the JVM is the core of Java, which is the essence of how Java can compile and run everywhere. I studied the composition and operating principles of the JVM, the Uniform data Format specification of the JVM, the bytecode file structure, and the JVM's memory management. the composition and operation principle of the JVM. After all,   JVM is a virtual machine, is a specification, although in line with von Neumann computer design concept, but he is not a physical computer, so his composition is not what memory, controller, arithmetic, input. In my opinion, the JVM is more like an application or a process running in a real operating system, and his composition can be understood as the functional modules of the JVM's process, and the functioning of these modules can be seen as the operating principle of the JVM. The JVM has several implementations, such as Oracle's JVM,HP JVM and IBM's JVM, and the study in this article is the most widely used Oracle hotspot JVM.   1.JVM the location in the JDK.   JDK is a necessary toolkit for Java development, part of which is Jre,jre is the Java Runtime Environment, and the JVM is the most central part of the JRE. I intercepted a composition of the JDK standard edtion from oracle.com, from the bottom of the list to see how important the JVM is, and the performance optimization of the Java application in the actual project, The processing of an exception such as Oom will eventually have to be resolved from the JVM. Hotspot is Oracle's trademark on the JVM, which differs from the JVM developed by vendors such as IBM,HP. Java hotspot Client VMs and Java Hotspot Server VMs are JDK's two different types of JVM, the former can reduce startup time and memory consumption, while the latter provides a more excellent program run speed (see: http://docs.oracle.com/javase/8/docs/technotes/guides/vm/index.html   This document has an introduction to each version of the JVM). On the command line, you can view information about the current machine JVM through Java-version, the following is the, of my command on the WIN8 system I can see that I'm loading the build 20.13-b02 version, HotSpot The JVM of type server mode. The composition   JVM of   2.JVM consists of 4 major parts: Classloader,runtime Data area,execution Engine, Native Interface. I got a diagram from CSDN that describes the approximate structure of the JVM: 2.1.classloader is responsible for loading the class file, the class file has a specific file mark at the beginning of the file, And ClassLoader is only responsible for the class file loading, as to whether it can run, it is determined by execution engine. 2.2.native Interface is responsible for invoking the local interface. His role is to call the different languages of the interface to Java, he will record the corresponding local method in the native method stack, and then call the method through the execution engine to load the corresponding local lib. Originally more than using some specialized fields, such as Java driver, map making engine, etc., now the call to this local method interface has been replaced by the same way as socket communication, webservice and so on. 2.3.execution engine is the execution of engines, also known as interpreter. When the class file is loaded, the instruction and data information is put into memory, and execution engine is responsible for interpreting the commands to the operating system. The 2.4.runtime data area is stored in five parts: Stack,heap,method area,pc register,native Method Stack. Almost all theThe problem with Java memory is focused on this piece. Is javapapers.com on the Run-time Data areas Description: can see that it has the method area as part of the heap, javapapers.com that the method Area is the logical region of the heap, but it depends on the JVM's implementation, while the hotspot JVM divides the method area into non-heap memory, which is clearly not included in the heap. In Javacodegeeks.com, the September 2014 issue of a blog post about the runtime Data area, which states that Nonheap contains PermGen and code Cache,permgen contains method area, And PermGen is no longer used in Java SE 8. Access to Information (https://abhirockzz.wordpress.com/2014/03/18/java-se-8-is-knocking-are-you-there/) informed that PermGen in Java8 has been removed from the JVM and replaced by Metaspace, and the Oom:permgen space exception is not seen in Java8. The runtime Data area can be used to describe its composition: 2.4.1.stack is the Java stack memory, which is equivalent to the C language of the stack, the memory address of the stack is not contiguous, each thread has its own stack. stored in the stack is StackFrame, in the "JVM specification" in the Chinese version of the Java Virtual Machine framework, also known as the stack frame. StackFrame contains three types of information: local variables, execution environment, and operand stacks. Local variables are used to store the local variables used in a method of a class. The execution environment is used to hold the information that the parser needs to interpret the Java bytecode, including: The Last method called, the local variable pointer, and the stack top and bottom pointer of the operand stack. The operand stack is used to store the operands and results required for the operation. StackFrame is created when the method is called, in a thread, at some point in time, only one frame is active, the frame is called the current frame, and the method in the framework is called the current method, where the class defined is the current class. Local variables and operations on the operand stack always refer to the current frame. When a method in a stack frame is executed, or when a method in another stackframe is called, the current stack changesFor another stackframe. The stack size is made up of two types, fixed and dynamic, and dynamic types of stacks can be allocated according to the needs of the thread. The following two graphs are a basic description of the relationship between stacks and the relationship between stacks and non-heap memory (from http://www.programering.com/a/MzM3QzNwATA.html): 2.4.2. Heap is used to hold object information, unlike a stack, which represents the state of a runtime. In other words, the stack is a run-time unit that solves the problem of how the program executes, while the heap is the stored unit that solves the data store problem. The heap is created with the start of the JVM and is responsible for storing all object instances and arrays. Heap storage space and stack is not required continuous, it is divided into young Generation and old Generation (also known as tenured generation) two parts. Young generation is divided into Eden and Survivor,survivor and is divided into from space and tospace. The concept of and heap is often mentioned as Permanentspace, which is the dedicated memory area used to load class objects, non-heap memory, and heap together to form Java memory, It contains the Methodarea area (Methodarea is equivalent to Generationspace in HOTSPOTJVM implementations without codecache). When the JVM is initialized, we can specify by parameters, the size of the permanentspace, the size of the heap, and the ratio of young generation and old generation, the ratio of the Eden area to the From space, This allows for fine-grained adaptation to the memory requirements of different Java applications.   2.4.3.PC Register is the program count register, each Java thread has a separate PC register, which is a pointer to the next instruction by execution engine. If the thread is executing a Java method, the PC register stores the address of the instruction being executed, and if it is a local method, the value of the PC register is not defined. The PC registers are very small and occupy only a single word width and can hold a pointer to a returnadress or a specific platform. 2.4.4.method area is not a part of the Hotspot JVM implementationThe heap area, the non-heap area consists of two parts: permanet generation and Code Cache, and the method area belongs to part of Permanert generation. Permanent generation is used to store class information, such as: Class Definitions,structures,methods, field, method (data and code), and constants. The code cache is used to store compiled code, the compiled native code, generated in the Hotspot JVM through the JIT (Just in time) compiler, JIT is the instant compiler, he is to improve the efficiency of instruction execution, The bytecode file compiled cost to machine code, such as: reference a classic case to understand the division of Stack,heap and Method area, that is sring a= "xx"; stirng b= "xx", ask whether a ==b? First, the = = symbol is used to determine whether the reference address of two objects is the same, and in the above topic, A and B are supposed to apply for different addresses in the stack, but they point to the same address of the runtime Constant pool in method area, according to the online explanation, When a is assigned to "XX", a string Constant is generated in the runtime contant pool, and when B is also assigned "XX", then the constant pool is checked to see if there are any constants with the value "XX", and if so, the pointer to B also points to the address of "XX". Instead of being reborn into a string Constant. I looked through the network of people about the storage of string constant, there is a slight difference is, where it is stored, it is said that the heap will be allocated a constant pool, used to store constants, all the threads share it. Some people say that the constant pool is part of the method area, and the method area belongs to the non-heap memory, how can it be said that the constant pool exists in the heap? I think the two kinds of understanding are right. The Method area is logically a part of the heap, and in some JVM implementations a storage space is created from the heap to record constants that are consistent with the JVM's constant pool design, so the previous statement is not a problem. For the latter, it is true that the HotSpot JVM is implemented by dividing the method partition into non-heap memory, meaning that it is not on the heap. I did a simple experiment with the hotspot JVM, after defining multiple constants,The program throws a Oom:permgen space exception, confirming that the constant pool in the JVM implementation is in permanent space. However, my JDK version is 1.6. Access to information, JDK1.7 internedstrings is no longer stored in permanentspace, but is placed in the heap, JDK8 Permanentspace has been completely removed, internedstrings is also placed in metaspace (if memory overflow Out, will report Oom:metaspace, here is a comparison between the performance of the article:http://blog.csdn.net/zhyhang/article/details/17246223 ). So, the benevolent see, a steamed bun enough to trigger a murder, even the same business of the JVM, after all, the JDK version is updated, perhaps as the stackoverflow of the Great God said, for understanding the JVM Runtime Data area This part of the Division logic, or to see the corresponding version of the JDK source code is more reliable, or refer to different versions of the JVM specification ( http://docs.oracle.com/javase/specs/ ). The 2.4.5.native method stack is a stack that is used by local methods (not Java). Each thread holds a native Method Stack. Introduction to operating principles of   3.JVM Java After the program is compiled into a. Class bytecode file by the Javac tool, we execute the Java command, which is loaded by the JVM's class loader, and you can see that the JVM was started by Java.exe or Java under Java path. The initialization of the JVM, the run-to-end, probably includes a few steps: invoking the OS API to determine the CPU architecture of the system, looking for the/lib/in the JRE directory based on the corresponding CPU type Jvm.cfg file, and then find the corresponding Jvm.dll file through the configuration file (if we have-server or-client in our parameters, Load the Jvm.dll specified by the corresponding parameter, start the JVM of the specified type, initialize the Jvm.dll and attach to the instance of the JNIENV structure, and then load and process the clas through the JNIEnv instanceS file now. The class file is a bytecode file that defines the details of variables, methods, and so on, according to the JVM's specifications, and the JVM manages and allocates the corresponding memory to execute the program while managing garbage collection. Until the end of the program, one case is that all non-daemon threads of the JVM are stopped, one in which the program calls System.exit (), and the life cycle of the JVM ends. about how the JVM manages allocated memory, I learned through the class file and garbage collection two parts.
Second, the JVM's memory management and garbage collection
Memory management in the JVM mainly refers to the management of the heap by the JVM, because both the STACK,PC register and the native Method stack are the same life cycle as the thread, and can be used again at the end of the process. Although the management of the stack is not the focus, it is not entirely inappropriate.
1. Management of Stacks
The JVM allows the stack size to be fixed or dynamically variable. In Oracle's official documentation for parameter settings, there are settings for the stack (http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/ optionx.html#wp1024112), is set to its size by-XSS. The default size of the stack is different for different machines, and the implementations of the JVM with different vendors or version numbers differ in size, as the following table is the default size of the hotspot:
Platform |
Default |
Windows IA32 |
KB |
Linux IA32 |
KB |
Windows x86_64 |
KB |
Linux x86_64 |
KB |
Windows IA64 |
KB |
Linux IA64 |
1024x768 KB (1 MB) |
Solaris Sparc |
KB |
We generally reduce the growth of the stack by reducing the number of constants and parameters, and in programming, we define some constants into an object and then reference them to reflect this. In addition, fewer recursive calls can also reduce the stack footprint. Stack does not need garbage collection, although garbage collection is a very hot topic in Java memory management, the object in the stack if the point of view of garbage collection, he is always live state, can be reachable, so do not need to recycle, he occupies the space with the end of the thread to release. (Reference from: http://stackoverflow.com/questions/20030120/java-default-stack-size)
about stacks the following two kinds of abnormal: 1 are generally encountered. Stackoverflowerror is thrown when the stack required for calculations in a thread exceeds the allowable size.   2. When the Java stack tries to expand, there is not enough memory to implement the extension, and the JVM will report OutOfMemoryError. I experimented with stacks, because recursive calls can cause the stack's references to increase, resulting in overflow, so the design code is as follows: my machine is a x86_64 system, so the default size of stack is 128KB , the above program will be error: at run time the exception disappears when I adjust the-XSS parameter to 3M in Eclipse. on the other hand, it is important to note that for local code calls, memory may be requested on the stack, such as C calling malloc (), in which case the GC is not a control and requires us to manually manage the stack memory in the program, using free () method to free up memory. 2. Heap management heap management is much more complex than stack management, and I work through the various parts of the heap, the settings, and the exceptions that can occur in each part, and how to avoid the various parts of the exception to learn. is a combination of heap and permanentsapce, where the eden area is a newborn object, from space and to space are stored in each garbage collection after the survival of the object, so after each garbage collection, The Eden area will be emptied. The surviving object is first placed in from space and then moved to To space when the from space is full. When the to space is full, move to the old space. The two districts of the survivor are symmetrical and have no succession, so the same district may have objects copied from Eden at the same time, and objects copied from the previous survivor, and copied to the old quarter only from the first survivor. Moreover, there is always an empty survivor area. At the same time, according to the program needs, the survivor area can be configured as multiple (more than two), which can increase the time of the object in the younger generation, reduce the possibility of being put into the old generation. old space is stored inLonger life-cycle objects, and some of the larger new objects are placed in old space. Heap size by-XMS and-xmx to specify the minimum and maximum values,-xmn to specify the size of young generation (some older versions are also specified with-xx:newsize), That is, the total size of Eden plus Fromspace and tospace in. The Eden area is then specified by-xx:newratio, which does not need to be set if XMS and Xmx are equal. Use-xx:survivorratio to set the ratio of Eden to a survivor area. (See from blog: http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html) heap anomalies are divided into two types, one of which is out of Memory (OOM), a memory Leak (ML). Memory leak will eventually lead to Oom. The actual application shows: From the console, the memory monitoring curve has been at the top, the program response is slow, from the thread view, most of the threads in the GC, occupy more CPU, the final program terminated abnormally, reported to Oom. Oom occurs in uncertain time, has a short one hours, has a long 10 days and one months. Regarding the handling of the exception, determine the OOM/ML exception, be sure to pay attention to the protection of the site, you can dump heap, if there is no field to open Gcflag collect garbage collection log, and then analyze to determine the problem. If the problem is not ml, it is common to modify the program logic by increasing the heap and increasing the physical memory to solve the problem. 3. Garbage collection   JVM will trigger recycling in the following situations: The object is not referenced, the scope is not caught, the program executes properly, the program executes the System.exit (), An unexpected termination of the program occurred.   JVM is a root search algorithm for the use of tags in garbage. To put it simply, start with an object called GC roots, search down, and if an object cannot reach the GC roots object, it can be recycled. This algorithm is better than a garbage-tagging algorithm called reference counting, because it avoids the fact that two objects cannot be recycled when they are referenced to one another.   JVM is divided into 3 algorithms: 1 when the object being marked as garbage is recycled. Tag cleanup algorithm,The algorithm scans the entire space from the root set, tags the surviving objects, and then reclaims the objects that are not tagged in the entire space, which is more efficient when there are many surviving objects, but produces memory fragmentation. 2. Copy algorithm, which scans from the root set and copies the surviving objects to a new space, which is more efficient in the case of surviving objects.   3. Tag grooming algorithm, the tag grooming algorithm and the tag cleanup algorithm will scan and tag the surviving objects, while the object is recycled, the tagged objects are collated, which solves the problem of memory fragmentation.    JVM, different memory areas are not the same, and the garbage collection algorithms used are not the same, so there are several different garbage collector definitions in the JVM (the wiring on the diagram represents two of the collector can be used simultaneously): 1.serial GC. From the name, the serial GC means that it is a single thread, so it requires all threads to be paused when collected. This is unreasonable for high-performance applications, so the serial GC is typically used in the client-mode JVM. 2.parnew GC. is on the basis of SERIALGC, added multithreading mechanism. But if the machine is a single CPU, this collector is less efficient than the SERIALGC. 3.parrallel scavenge GC. This collector is also known as the throughput priority collector, while throughput = program run time/(the JVM recycles time + program run time), assuming the program is running for 100 minutes and the JVM's garbage collection takes 1 minutes, then throughput is 99%. The Parallel scavenge GC has been used as the default configuration for the server-mode JVM because it can provide good throughput. 4.parallelold is a parallel collector of the Laosheng generation, using the labeling algorithm, is introduced in the JDK1.6, before the Laosheng generation can only use the serial recovery collector. 5.serial old is the default collector in the Laosheng client mode, single-threaded execution, and also as an alternate collector after the CMS collector fails. 6.cms, also known as the response time priority collector, uses the tag cleanup algorithm. His number of recycled threads is (CPU core number +3)/4, so it is more efficient when the CPU cores are 2. The CMS is divided into 4 processes: initial tag, concurrency token, re-tagging, concurrency cleanup. 7.garbagefirst (G1). The more special is that the G1 collector can recover young Generation or tenured Generation. It was introduced in a version of JDK6, with high performance while paying attention to throughput and response time. for a combination of garbage collectors, you can specify: the default GC type by using the parameters in the following table, which can be viewed through jvm.cfg or Jmap dump heap. Generally we can see the general situation of GC per second through Jstat-gcutil [PID] 1000, or can be added in the startup parameters:-verbose:gc-xx:+printgctimestamps-xx:+printgcdetails- Xloggc:./gc.log to record GC logs.   GC There is a situation called full GC, the following conditions will trigger full gc: 1.tenured space is not enough to create a hit object or array, will execute FULLGC, And if the space is not enough after the FULLGC, then Oom:java will be in the heap. 2.permanet generation is insufficient in size, storing too much class information, triggering FULLGC in the non-CMS case. If the space is not enough later, it will Oom:permgen. When promotion failed and concurrent mode failure appear when 3.cms GC, FULLGC is also triggered. Promotion failed is in the minor GC, Survivor space, the object can only be placed in the old generation, and at this time the old generation also can not put the cause; Concurrent mode failure is executing CMS In the process of GC, there are objects to be put into the old generation, while the old generation space is insufficient. 4. After judging minorgc, the size of the object to be promoted to Tenuredspace is greater than the size of tenuredspace, which also triggers FULLGC. It can be seen that when FULLGC occurs frequently, there must be memory problems. Data Format specification for JVM and CLThe 1. Data type specification According to von Neumann's computer theory, the final processing of the computer is the number of binaries, And how does the JVM translate Java files into binary systems that can be identified by each platform? The JVM itself defines an abstract unit of stored data, called Word. A word large enough to hold a value of Byte, char, short, int, float, reference, or returnadress, and two words is sufficient to hold a larger type long, double. It is usually the size of a pointer to a host platform, such as a 32-bit platform, the word is 32 bits. at the same time, the JVM defines the basic data types it supports, including two parts: numeric types and ReturnAddress types. Numeric types are divided into shaping and floating-point type. Shaping:
Byte |
The value is a 8-bit signed twos complement integer |
Short |
The value is a 16-bit signed twos complement integer |
Int |
The value is a 32-bit signed twos complement integer |
Long |
The value is a 64-bit signed twos complement integer |
Char |
Value is a 16-bit unsigned integer that represents a Unicode character |
Floating point:
Float |
Value is 32-bit IEEE754 floating-point number |
Double |
Value is 64-bit IEEE754 floating-point number |
The value of the ReturnAddress type is a pointer to the opcode of the Java Virtual machine instruction. Compared to Java's basic data types, there is no Boolean type in the JVM's specification. This is because the heap Boolean operation in the JVM is handled by the int type, and the Boolean array is processed by a byte array. As for string, we know that it is stored in a constant pool, but he is not a basic data type, and it can exist in a constant pool because it is a rule of the JVM. If we look at the string source, we will find that the string is actually an array based on the basic data type char: 2. Bytecode files through the format of the bytecode file we can see how the JVM regulates the data type. Here is the structure of the Classfile: definitions for each field (refer to the JVM Specification and blog post: http://www.cnblogs.com/zhuYears/archive/2012/02/07/2340347.html),
Magic
Magic number, the only function of the magic number is to determine whether the file is a virtual machine can be accepted by the class file. The magic value is fixed to 0xCAFEBABE and does not change.
Minor_version, Major_version:
The secondary and major versions of the class file, respectively. Together they form the format version number of the class file. Different versions of the virtual machine implementation support for the class file version number is also different, the higher version of the virtual machine can support the lower version of the class file, the reverse is not true.
Constant_pool_count:
Constant pool counter, the value of Constant_pool_count equals the number of members in the Constant_pool table plus 1.
Constant_pool[]:
Constant pool, constant_pool is a table structure that contains all the string constants, class or interface names, field names, and other constants referenced in the class file structure and its sub-structures. The constant pool differs from the others, and the index starts at 1 to constant_pool_count-1.
Access_flags:
An access flag, Access_flags, is a mask flag that represents the access rights and underlying properties of a class or interface. The value range and the corresponding meanings of access_flags are shown in the following table:
This_class:
Class index, the value of This_class must be a valid index value for the item in the Constant_pool table. The Constant_pool table at this index must be a Constant_class_info type constant, representing the class or interface defined by the class file.
Super_class:
The parent class index, for classes, the value of Super_class must be 0 or a valid index value for an item in the Constant_pool table. If its value is not 0, then the entry at this index of the Constant_pool table must be a Constant_class_info type constant, representing the immediate parent class of the class defined by the class file. Of course, if the value of a class Super_class is 0, then it must be the Java.lang.Object class, because only it has no parent class.
Interfaces_count:
Interface counter, the value of Interfaces_count represents the number of direct parent interfaces for the current class or interface.
Interfaces[]:
The value of each member in the interface table, interfaces[] array must be a valid index value for the item in the Constant_pool table, and its length is interfaces_count. Each member Interfaces[i] must be a constant_class_info type constant.
Fields_count:
Field counter, the value of Fields_count represents the number of members of the current class file fields[] array.
Fields[]:
Each member in the Field table, fields[] array must be a data item of the FIELDS_INFO structure that represents the complete description of a field in the current class or interface.
Methods_count:
The value of the Methods_count method counter, which represents the number of members of the current class file methods[] array.
Methods[]:
Each member of the method table, methods[] array must be a data item of the METHOD_INFO structure that represents the complete description of a method in the current class or interface.
Attributes_count:
The value of the Attributes_count property counter, which represents the number of members of the current class file attributes table.
Attributes[]:
property sheet, the value of each item of the attributes table must be a attribute_info structure.
四、一个 Instance Analysis of Java classes in order to understand the data type specification and memory allocation of the JVM in general, I have created memerytest.java: After compiling to Memerytest.class, through Winhex to view the file, corresponding to the different parts of the bytecode file definition, I understand the following 16 binary values of the specific meaning, although not clear classloader specific implementation logic, but can imagine such a rigorous format of the file to the JVM for memory management And how much help is provided by the implementation process. after running the program, I found the corresponding process ID in Windows Explorer. and view heap memory usage in the console via Jmap-heap 10016: The output shows that the JVM that is currently started by the Java process is parallel GC with 4 threads, the minimum freeratio of the heap is 40%, the heap is the maximum freeratio is 70%, the heap size is 4090M, and the new object occupies 1.5m,young Generation can be extended to a maximum of 1363M, the size of tenured generation is 254.5M, as well as Newradio and Survivorradio, the following is specifically given the current young Generation 1.5M in the division, Eden occupies 1.0M, using the 5.4%,space accounted for 0.5M, using the 93%,to space accounted for 0.5M, using 0%. Below we print the contents of the heap through Jmap dump to the file: open the corresponding file using the eclipse's Mat plugin: Select the first memory leak analysis report to open the Test.bin file, showing the mat's analysis of possible memory leaks. As a result, there are 3 places where memory leaks can occur, they occupy the heap's 22.10%,13.78%,14.69%, and if memory leaks, there is usually a very high ratio of objects. Open the first probem Suspect, the results are as follows: shallowheap is the size of the heap occupied by the object itself, does not contain references, retainedheap is the size of the SHALLOWHEAP held by the object, the packageThe shallowheap of Shallowheap and the objects that can be referenced. Garbage collection, if an object is no longer referenced and then recycled, then his retainedheap is the sum of memory that can be recycled. Can be seen through the program and there is no memory leaks, you can rest assured. If there are any objects that are not sure, you can study the change of an object by Heapdumpfile at multiple points in time. Five, summary above is my recent days on the JVM related data collation, mainly around his basic composition and operating principles, such as memory management, abridged data types and bytecode files. The JVM is a very good Java program, but also a good specification, this finishing learning let me have a clearer understanding of him, the Java language also deepened. This learning process has strengthened my understanding of programmer development. Knowledge must be refined, next I will work while reading the Oracle's 3 version of the "JVM specification", and combined with practice to make their own Java basic literacy level. (http://docs.oracle.com/javase/specs/)
Knowledge of the JVM collation and Learning-(reprint)