were set to true
.
If so, it invokes resolveClass()
, passing the Class
instance returned by defineClass()
.
The resolveClass()
method links the class. resolveClass()就是对class进行link操作
Finally, loadClass()
returns the newly created Class
instance:
这里loadClass()返回成功
if (resolveIt) { resolveClass(result); } // Return class from basePath directory return result;
Using a 1.2 User-Defined Class Loader
The class loader described in the previous section,
which was originally designed for a 1.1 virtual machine,
will still work in 1.2.
Although 1.2 added a concrete default implementation of loadClass()
to java.lang.ClassLoader
,
this concrete method can still be overridden in subclasses.
Because the contract of loadClass()
did not change from 1.1 to 1.2,
legacy user-defined class loaders that override loadClass()
should still work as expected in 1.2.
The basic contract of loadClass()
is this:
Given the fully qualified name of the type to find,
the loadClass()
method should in some way attempt to locate or produce an array of bytes,
purportedly in the Java class file format, that define the type.
If loadClass()
is unable to locate or produce the bytes, it should throw ClassNotFoundException
.如果加载byte[]不成功，抛出异常
Otherwise, loadClass()
should pass the array of bytes to 如果加载byte[]成功，接着调用defineClass()方法
one of the defineClass()
methods declared in class ClassLoader
.
By passing the byte array to defineClass()
,
loadClass()
asks the virtual machine to import the type
represented by the passed byte array
into the namespace of this user-defined class loader.
When loadClass()
calls defineClass()
in 1.2,
it can also specify a protection domain with which the type data should be associated.
When the loadClass()
method of a class loader successfully loads a type,返回一个Class对象
it returns a java.lang.Class
object to represent the newly loaded type.
The concrete implementation of loadClass()
from class java.lang.ClassLoader
fulfills the loadClass()
method's contract using these four basic steps:
-
See if the requested type has already been loaded into this class loader's namespace (via
findLoadedClass()
). If so, return theClass
instance for that already-loaded type. 查看是否已经加载过该类 -
Otherwise, delegate to this class loader's parent loader.
If the parent returns a
Class
instance, return that sameClass
instance. 先交给parent loader进行加载 -
Otherwise, invoke
findClass()
, which should attempt to locate or produce an array of bytes, purportedly in the Java class file format, that define the desired type. If successful,findClass()
should pass those bytes todefineClass()
, which will attempt to import the type and return aClass
instance. IffindClass()
returns aClass
instance,loadClass()
returns that sameClass
instance. 自己进行加载 -
Otherwise,
findClass()
completes abruptly with some exception, andloadClass()
completes abruptly with the same exception. 加载失败
Although in 1.2 you can still subclass ClassLoader
and override the loadClass()
method,
the recommended approach to creating your own user-defined class loader in 1.2
is to subclass ClassLoader
and implement the findClass()
method.推荐方式是重写findClass()方法
The findClass()
method looks like this:
// A method declared in class java.lang.ClassLoader: protected Class findClass(String name) throws ClassNotFoundException;
The basic contract of the findClass()
method is this:
findClass()
accepts the fully qualified name of a desired type as its only parameter.接收参数
findClass()
first attempts to locate or produce an array of bytes,查找byte[]
purportedly in the Java class file format, that define the type of the requested name.
If findClass()
is unable to locate or produce the array of bytes,无法找到byte[]
it completes abruptly with ClassNotFoundException
.
Otherwise, findClass()
invokes defineClass()
,如果找到byte[]，调用defineClass()方法
passing in the requested name, the array of bytes and,
optionally, a ProtectionDomain
object with which the type should be associated.
If defineClass()
returns a Class
instance for the type,返回结果
findClass()
simply returns that same Class
instance to its caller.
Otherwise, defineClass()
completes abruptly with some exception,出现异常
and findClass()
completes abruptly with the same exception.
这里就是对findClass()方法进行介绍
Here's a version of GreeterClassLoader
that,
rather than overriding loadClass()
, merely overrides findClass()
:
// On CD-ROM in file // linking/ex7/com/artima/greeter/GreeterClassLoader.java package com.artima.greeter; import java.io.*; public class GreeterClassLoader extends ClassLoader { // basePath gives the path to which this class // loader appends "/<typename>.class" to get the // full path name of the class file to load private String basePath; public GreeterClassLoader(String basePath) { this.basePath = basePath; } public GreeterClassLoader(ClassLoader parent, String basePath) { super(parent); this.basePath = basePath; } protected Class findClass(String className) throws ClassNotFoundException { byte classData[]; // Try to load it from the basePath directory. classData = getTypeFromBasePath(className); if (classData == null) { throw new ClassNotFoundException(); } // Parse it return defineClass(className, classData, 0, classData.length); } private byte[] getTypeFromBasePath(String typeName) { FileInputStream fis; String fileName = basePath + File.separatorChar + typeName.replace('.', File.separatorChar) + ".class"; try { fis = new FileInputStream(fileName); } catch (FileNotFoundException e) { return null; } BufferedInputStream bis = new BufferedInputStream(fis); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { int c = bis.read(); while (c != -1) { out.write(c); c = bis.read(); } } catch (IOException e) { return null; } return out.toByteArray(); } }
This version of GreeterClassLoader
appears in the linking/ex7
directory of the CD-ROM.
All of the source files in linking/ex6
,
which were described in detail in previous sections,
appear unchanged in linking/ex7
, except for GreeterClassLoader.java
.
Where the GreeterClassLoader
class,
described in the previous section,
that overrides loadClass()
appears in linking/ex6
,
the GreeterClassLoader
, described in this section,
that overrides findClass()
appears in linking/ex7
.
This second version of GreeterClassLoader
declares one instance variable, basePath
,
which is a String
that is used to store the directory path
in which findClass()
should look for the class file of the type it has been requested to load.
The basePath
String
is the only parameter passed to GreetingClassLoader
's 1-arg constructor.
Because the 1-arg constructor accepts no reference to a caller-specified parent class loader,
this class loader can't invoke the superclass constructor that takes a reference to a user-defined class loader.
Thus, it simply invokes the superclass's no-arg constructor by default, which sets this class loader's parent to be the system class loader.
The other constructor (the 2-arg constructor), however,
accepts a reference to a user-defined class loader instance as well as the basePath
String
.
This constructor explicitly invokes the superclass's 1-arg constructor, passing along the reference.
The superclass sets this class loader's parent to be the passed user-defined class loader instance.
介绍GreeterClassLoader的字段和构造方法。
By comparing the implementation of findClass()
in this version of GreeterClassLoader
with
the implementation of loadClass()
in the previous version of GreeterClassLoader
,
you can easily see how much simpler it is to write findClass()
than loadClass()
.
You have much less to worry about when you write findClass()
, and fewer opportunities to make mistakes.
findClass()
merely invokes getTypeFromBasePath()
to attempt in this user-defined class loader's custom way to load the requested type.
If getTypeFromBasePath()
is unable to locate the requested type in the basePath
directory,
it returns null
and findClass()
throws a ClassNotFoundException
.
Otherwise, getTypeFromBasePath()
returns the array of bytes,
which findClass()
simply passes on to defineClass()
.
If defineClass()
returns a reference to a Class
instance to represent the successfully loaded type,
findClass()
returns that same reference.
Otherwise, defineClass()
completes abruptly with an exception,
which causes findClass()
to complete abruptly with the same exception.
使用findClass()，而不使用loadClass()，这么做会更简单、更不容易出错
The findClass()
method's contract is a subset of the loadClass()
method's contract.
findClass()
isolates the only two parts of loadClass()
that should in general be customized by subclasses of java.lang.ClassLoader
:
这里说明findClass()是loadClass()的一个“子集”
- the custom manner in which an array of bytes is located or produced given a fully qualified type name
- optionally, the custom manner in which a type's protection domain is determined
When an implementation of findClass()
performs these two tasks,
the result is an array of bytes and a reference to a ProtectionDomain
object.
findClass()
passes both the byte array and the ProtectionDomain
reference to defineClass()
.
Example: Dynamic Extension with forName()
As an example of a Java application that performs dynamic extension with forName()
, consider the EasyGreet
class:
// On CD-ROM in file linking/ex7/EasyGreet.java import com.artima.greeter.*; public class EasyGreet { // Arguments to this application: // args[0], args[1], ... - class names of greeters to load // and invoke the greet() method on. // // All greeters must implement the com.artima.greeter.Greeter // interface. // static public void main(String[] args) { if (args.length == 0) { System.out.println("Enter greeter class names as args."); return; } for (int i = 0; i < args.length; ++i) { try { // Load the greeter specified on the command line Class c = Class.forName(args[i]); // Instantiate it into a greeter object Object o = c.newInstance(); // Cast the Object ref to the Greeter interface type // so greet() can be invoked on it Greeter greeter = (Greeter) o; // Greet the world in this greeter's special way greeter.greet(); } catch (Exception e) { e.printStackTrace(); } } } }
The EasyGreet
application is very similar to the Greet
application from the previous example.
Like Greet
, EasyGreet
will attempt to dynamically load and execute greeters mentioned in command line arguments.相似之处
But unlike Greet
, EasyGreet
doesn't take as its first command line argument a path name of the directory不同之处
in which the class files for the greeters are stored.
All of EasyGreet
's command line arguments are greeter class names.
Another difference is that EasyGreeter
,
because it is going to use forName()
to load greeters dynamically,
doesn't instantiate a GreeterClassLoader
.
Then, where Greet
invoked loadClass()
on its GreeterClassLoader
instance,
EasyGreet
invokes forName()
, a static method of class Class
.
这是主要是比较Greet和EasyGreet两者的差异
EasyGreet
's forName()
invocation looks very similar to Greet
's loadClass()
invocation.
Like loadClass()
, forName()
accepts the fully qualified name of the requested type in a String
parameter.
If successful in loading the type (or if the type had been loaded previously),
forName()
, like loadClass()
, returns the Class
instance that represents the type.
If unsuccessful, forName()
, like loadClass()
, throws ClassNotFoundException
.
The big difference between the two approaches is that
whereas loadClass()
attempts to ensure the requested type is loaded into the user-defined class loader's namespace,
forName()
attempts to ensure the requested type is loaded into the current namespace --
the namespace of the defining class loader for the type whose method includes the forName()
invocation.
这里主要是比较loadClass()和forName()之间的差异。
Because forName()
is invoked from the main()
method of class EasyGreet
,
the class loader that forName()
asks to load the requested type is EasyGreet
's defining class loader.
When run from Sun's Java 2 SDK version 1.2, the class loader that loads EasyGreet
is the system class loader,
which looks for classes on the class path.
To use the class path environment variable, you can execute the EasyGreet
application
in the linking/ex7
directory of the CD-ROM with a command like this:
java EasyGreet Hello
If you don't specify a class path either explicitly on the command line or in an environment variable,
the system loader will look in the current directory for requested types.
Because the current directory (the linking/ex7
directory from the CD-ROM) doesn't contain Hello.class
,
the system class loader is unable to locate Hello.class
.
The forName()
method, and in turn EasyGreet
's main()
method,
completes abruptly with a ClassNotFoundException
:
如果不指定class path，就找不到相应的类。
To enable EasyGreet
to find Hello.class
merely requires that
the greeters
directory be included in a class path specified on the command line
with the "-cp
" option, as in:
添加class path信息
java -cp .;greeters; EasyGreet Hello
When started with this command, the EasyGreet
program prints:
Hello, world!
Like the Greet
method, EasyGreet
will accept multiple greeter names on the command line:
java -cp .;greeters; EasyGreet Hello Greetings Salutations HowDoYouDo
When invoked with this command, the EasyGreet
application will load each of the four greeters listed and invoke their greet()
methods, yielding this output:
Hello, world! Greetings, planet! Salutations, orb! How do you do, globe!
The important difference that arises from Greet
's use of loadClass()
on GreeterClassLoader
and
EasyGreet
's use of forName()
is
the namespaces into which the greeter classes get loaded.差异，就是引入的namespace不同
In Greet
, the greeter classes get loaded into the GreeterClassLoader
's namespace.
In EasyGreet
, the greeter classes get loaded into the system class loader's namespace.
两个程序的主要差异，就是引入的namespace是不同的。
Example: Unloading Unreachable Greeters
As an example of dynamically loaded types becoming unreachable and getting unloaded by the virtual machine,
consider the following application:
// On CD-ROM in file linking/ex7/GreetAndForget.java import com.artima.greeter.*; public class GreetAndForget { // Arguments to this application: // args[0] - path name of directory in which class files // for greeters are stored // args[1], args[2], ... - class names of greeters to load // and invoke the greet() method on. // // All greeters must implement the com.artima.greeter.Greeter // interface. // static public void main(String[] args) { if (args.length <= 1) { System.out.println("Enter base path and greeter class names as args."); return; } for (int i = 1; i < args.length; ++i) { try { GreeterClassLoader gcl = new GreeterClassLoader(args[0]); // Load the greeter specified on the command line Class c = gcl.loadClass(args[i]); // Instantiate it into a greeter object Object o = c.newInstance(); // Cast the Object ref to the Greeter interface type // so greet() can be invoked on it Greeter greeter = (Greeter) o; // Greet the world in this greeter's special way greeter.greet(); // Forget the class loader object, Class // instance, and greeter object gcl = null; c = null; o = null; greeter = null; // At this point, the types loaded through the // GreeterClassLoader object created at the top of // this for loop are unreferenced and can be unloaded // by the virtual machine. } catch (Exception e) { e.printStackTrace(); } } } }
The GreetAndForget
application accepts the same command line arguments as the Greet
application of the previous example.
The first argument is a base directory path name where the GreetAndForget
application will look for greeters.
Subsequent arguments are greeter names.
To understand this example you should be familiar with the Greet
application presented earlier in this chapter.
这个程序与前面的Greet程序很相似
Imagine you invoke the GreetAndForget
application with the following command line:
java GreetAndForget greeters Surprise HiTime Surprise
The code for the HiTime
greeter,
which selects a different greeting based on the time of day,
is shown above in the previous section of this chapter.
The code for the Surprise
greeter,
which pseudo-randomly selects one of four helper greeters--
Hello
, Greetings
, Salutations
, or HowDoYouDo
--
and invokes its greet()
method, is shown here:
// On CD-ROM in file linking/ex7/greeters/Surprise.java import com.artima.greeter.Greeter; public class Surprise implements Greeter { public void greet() { // Choose one of four greeters pseudo-randomly and // invoke its greet() method. int choice = (int) (Math.random() * 3.99); Greeter g; switch(choice) { case 0: g = new Hello(); g.greet(); break; case 1: g = new Greetings(); g.greet(); break; case 2: g = new Salutations(); g.greet(); break; case 3: g = new HowDoYouDo(); g.greet(); break; } } }
Given the command line shown above,
the GreetAndForget
application invokes the greet()
method of the Surprise
greeter first,
then the HiTime
greeter, then the Surprise
greeter again.
GreetAndForget
's actual output would vary depending on the time of day and Surprise
's pseudo-random mood.
For the purposes of this example, assume that you typed in the above command, hit return, and got the following output:
How do you do, globe! Good afternoon, world! Greetings, planet!
This output indicates Surprise
chose to execute HowDoYouDo
's greet()
method the first time around and
Greetings
's greet()
method the second time around.
The first pass through GreetAndForget
's for loop,
the virtual machine loads the Surprise
class and invokes its greet()
method.
The constant pool for Surprise
includes a symbolic reference to each of the four helper greeters that it may choose:
Hello
, Greetings
, Salutations
, and HowDoYouDo
.
Assuming the Java virtual machine that you used to run the GreetAndForget
application uses late resolution,
only one of these four symbolic references will be resolved during the first pass of GreetAndForget
's for loop:
the symbolic reference to HowDoYouDo
.
The virtual machine resolves this symbolic reference
when it executes the bytecodes that correspond to the following statement in Surprise
's greet()
method:
g = new HowDoYouDo();
To resolve the symbolic reference from Surprise
's constant pool to HowDoYouDo
,
the virtual machine invokes the GreeterClassLoader
object's loadClass()
method,
passing the string "HowDoYouDo
" in the name
parameter.
The virtual machine uses the GreeterClassLoader
object to load HowDoYouDo
because Surprise
was loaded through the GreeterClassLoader
object.
As mentioned earlier in this chapter, when the Java virtual machine resolves a symbolic reference,
it uses the same class loader that defined the referencing type
(in this case, Surprise
) to initiate loading the referenced type (in this case, HowDoYouDo
).
Once Surprise
's greet()
method has created a new HowDoYouDo
instance,
it invokes its greet()
method:
g.greet();
As the virtual machine executes HowDoYouDo
's greet()
method,
it must resolve two symbolic references from HowDoYouDo
's constant pool--
one to class java.lang.System
and another to class java.io.PrintStream
.
To resolve these symbolic references,
the virtual machine invokes the GreeterClassLoader
object's loadClass()
method,
once with the name java.lang.System
and once with the name java.io.PrintStream
.
As before, the virtual machine uses the GreeterClassLoader
object to load these classes
because the referencing class--in this case, HowDoYouDo
--was loaded through the GreeterClassLoader
object.
But these two classes, both members of the Java API, will end up being loaded by the bootstrap class loader anyway,
because loadClass()
will first delegate to its parent.
值得一读，加载类的细节描述
Remember that before the loadClass()
method of GreeterClassLoader
attempts to look for a requested type in the base directory
(in this case, directory greeters
),
it invokes its parent, the system class loader.
The system class loader will first delegate to its parent, which will first delegate to its parent, and so on.
Eventually findSystemClass()
will be invoked to delegate to the bootstrap class loader, the end-point of the parent-delegation chain.
Because the bootstrap class loader (via findSystemClass()
) is able to load both java.lang.System
and java.io.PrintStream
,
the loadClass()
method will simply return the Class
instance returned by findSystemClass()
.
These classes will be marked not as having been loaded by the GreeterClassLoader
object,
but as having been loaded by the bootstrap class loader.
To resolve any references from java.lang.System
or java.io.PrintStream
,
the virtual machine will not invoke the loadClass()
method of the GreeterClassLoader
object,
or even the system class loader.
It will just use the bootstrap class loader directly.
值得一读，加载类的细节描述
As a result, after Surprise
's greet()
method has returned,
there will be two types marked as having been loaded by the GreeterClassLoader
object:
class Surprise
and class HowDoYouDo
.
These two types will be in the virtual machine's internal list of the types loaded by the GreeterClassLoader
object.
GreeterClassLoader加载了两个类
Just after Surprise
's greet()
method returns,
the Class
instances for Surprise
and HowDoYouDo
are reachable by the application.
The garbage collector will not reclaim the space occupied by these Class
instances,
because there are ways for the application's code to access and use them.
See Figure 8-11 for a graphical depiction of the reachability of these two Class
instances.
Figure 8-11. The reachability of the Class instances for Surprise and HowDoYouDo.
The Class
instance for Surprise
can be reached in two ways.
First, it can be reached directly from local variable c
of GreetAndForget
's main()
method.
Second, it can be reached from local variables o
and greeter
,
which both point to the same Surprise
object.
From the Surprise
object, the virtual machine can get at Surprise
's type data,
which includes a reference to Surprise
's Class
object.
获取该Class实例的两种方式
The Class
instance for HowDoYouDo
can be reached in two ways.
One way is identical to the one of the paths to the Class
instance for Surprise
:
the gcl
local variable of GreetAndForget
's main()
method points to the GreeterClassLoader
object,
which includes a reference to a HashTable
object.
The Hashtable
contains a reference to HowDoYouDo
's Class
instance.
The other way to reach HowDoYouDo
's class instance is through Surprise
's constant pool.
这段和上面那段都有问题，是因为Java版本更新和书版本更新造成的
When the virtual machine resolved the symbolic reference from Surprise
's constant pool to HowDoYouDo
,
it replaced the symbolic reference with a direct reference.
The direct reference points to HowDoYouDo
's type data,
which includes a reference to HowDoYouDo
's Class
instance.
Thus, starting from Surprise
's constant pool, the Class
instance to HowDoYouDo
is reachable.
But why would the garbage collector look at direct references emanating from Surprise
's constant pool in the first place?
Because Surprise
's Class
instance is reachable.
When the garbage collector finds that it can reach Surprise
's Class
instance,
it makes sure it marks the Class
instances for any types that are directly referenced from Surprise
's constant pool as reachable.
If Surprise
is still live, the virtual machine can't unload any types Surprise
may need to use.
Note that of the three ways, described above, that Surprise
's Class
instance can be reached,
none of them involve a constant pool of another type.
Surprise
does not appear as a symbolic reference in the constant pool for GreetAndForget
.
Class GreetAndForget
did not know about Surprise
at compile-time.
Instead, the GreetAndForget
application decided at run-time to load and link to class Surprise
.
Thus, the Class
instance for class Surprise
is only reachable
by starting from the local variables of GreetAndForget
's main()
method.
Unfortunately for Surprise
(and ultimately for HowDoYouDo)
, this does not constitute a very firm grasp on life.
The next four statements in GreetAndForget
's main()
method,
will change the reachability situation completely:
// Forget the user-defined class loader, Class // instance, and greeter object gcl = null; c = null; o = null; greeter = null;
These statements null out all four starting places from which Surprise
's Class
instance is reachable.
As a result, after these statements have been executed, the Class
instance for Surprise
is no longer reachable.
These statements also render unreachable the Class
instance for HowDoYouDo
,
the Surprise
instance that was formerly pointed to by the o
and greeter
variables,
the GreeterClassLoader
instance that was formerly pointed to by the gcl
variable,
and the Hashtable
instance that was pointed to by the classes variable of the GreeterClassLoader
object.
All five of these objects are now available for garbage collection.
Class和具体的instance对已经无法引用到的，就可以进行garbage collection了
When (and if) the garbage collector gets around to freeing the unreferenced Class
instances for Surprise
and HowDoYouDo
,
it can also free up all the associated type data in the method area for Surprise
and HowDoYouDo
.
Because these class's Class
instances are unreachable,
the types themselves are unreachable and can be unloaded by the virtual machine.
method area中的type data也要unload了
Note that two iterations of the for loop later (given the command line shown above),
the GreetAndForget
application will again load class Surprise
.
Keep in mind that the virtual machine will not reuse the type data for Surprise
that was loaded during the first pass of the for loop.
Granted, that type data became available for unloading at the end of the first pass.
But even if the Class
instance for Surprise
hadn't become unreferenced at the end of the first pass,
the type data from the first pass wouldn't be reused during the third pass.
Class不能重用，我觉得，是因为它是从不同的ClassLoader当中加载的
With each pass of the for loop, the main()
method of GreetAndForget
creates a new GreeterClassLoader
object.
Thus, every greeter that GreetAndForget
loads is loaded through a different user-defined class loader.
For example, if you invoke the GreetAndForget
application with the Hello
greeter listed five times on the command line,
the application will create five instances of class GreeterClassLoader
.
The Hello
greeter will be loaded five times by five different user-defined class loaders.
The method area will contain five different copies of the type data for Hello
.
The heap will contain five Class
instances that represent the Hello
class--
one for each namespace into which Hello
is loaded.
When one of the Class
instances for Hello
becomes unreferenced,
only the Hello
type data associated with that particular Class
instance would be available for unloading.
我猜测的是对的
Example: Type Safety and Loading Constraints
In early implementations of the Java virtual machine, it was possible to confuse Java's type system.
A Java application could trick the Java virtual machine into using an object of one type as if it were an object of a different type.这里应该说的就是type safety反面吧
This capability makes cracker's happy, because they can potentially spoof trusted classes to gain access to non-public data or
change the behavior of methods by replacing them with new versions.我觉得有点像Java Agent的行为
For example, if a cracker could write a class and successfully fool the Java virtual machine into thinking it was class SecurityManager
,
that cracker could potentially break out of the sandbox.
The example presented in this section is designed to help you understand the type safety problems that can arise with delegating class loaders,
and the loading constraints that appeared in the second edition of the Java virtual machine specification to address the problem.
总结：type safety在原来的版本中存在问题，而loading constraints的出现是为了修复type safety的问题。
The type safety problem arises because the multiple namespaces inside a Java virtual machine can share types.这里讲出现type safety的原因
If one class loader delegates to another class loader, and the delegated-to class loader defines the type,
both class loaders are marked as initiating loaders for that type.
The type defined by the delegated-to class loader is shared among all the namespaces of the initiating loaders of the type.
type safety problem出现的原因，是由于一个type可以在多个namespace中共享。
At compile time, a type is uniquely identifiable by its fully qualified name.在编译的时候，全限定名作为唯一标识。
For example, only one class named Spoofed
can exist at compile time.
At runtime, however, a fully qualified name is not enough to uniquely identify a type that has been loaded into a Java virtual machine.在运行的时候，全限定名就不能唯一确定了
Because a Java application can have multiple class loaders,
and each class loader maintains its own namespace,
multiple types with the same fully qualified name can be loaded into the same Java virtual machine.
Thus, to uniquely identify a type loaded into a Java virtual machine requires the fully qualified name and the defining class loader.
在运行的时候，a type = fully qualified name + defining class loader
The type safety problems made possible by this class loader architecture问题的出现，是由于compile-time和runtime时，两者的概念不统一造成的。
arose from the Java virtual machine's initial reliance on the compile time notion of a type being uniquely identifiable by only its fully qualified name.
You can always load two types both named Spoofed
into the same Java virtual machine.
Each Spoofed
class would be defined by different class loader.
But with a little finesse, you could fool an early implementation of the Java virtual machine into
treating an instance of one Spoofed
as if it were an instance of the other Spoofed
.
在早期的JVM版本当中，type safety problems会出现。
To address this problem, the second edition of the Java virtual machine specification introduced the notion of loading constraints.
Loading constraints basically enable the Java virtual machine to enforce type safety based not just on fully qualified name,
but also on the defining class loader, without forcing eager class loading.
When the virtual machine detects a potential for type confusion during constant pool resolution,
it adds a constraint to an internal list of constraints.
All future resolutions must satisfy this new constraint, as well as all other constraints in the list.
loading constraints出现就是为了解决type safety problems
For an example of the type confusion problem and its loading constraints solution,
consider this implementation of a greeter, written by a devious cracker:
// On CD-ROM in file linking/ex8/greeters/Cracker.java import com.artima.greeter.Greeter; public class Cracker implements Greeter { public void greet() { Spoofed spoofed = new Spoofed(); System.out.println("secret val = " + spoofed.giveMeFive()); spoofed = Delegated.getSpoofed(); System.out.println("secret val = " + spoofed.giveMeFive()); } }
Class Cracker
is a greeter, like Hello
or Salutations
of the previous examples,
because it implements the com.artima.greeter.Greeter
interface.
Class Cracker
is sitting in the linking/ex8
directory of the CD-ROM, along with other, more well-meaning, greeters.
All the classes from the linking/ex7
directory appear unchanged in linking/ex8
,
except for GreeterClassLoader
, which has been slightly modified. (More on this modification later.)
You can invoke Cracker
with the greet()
method just like any other greeter.
From the linking/ex8
directory, you can simply type:
java Greet greeters Cracker
The main()
method of Greet
will, as it did in the previous examples,
create a GreeterClassLoader
and invoke its loadClass()
method, passing in the name Cracker
.
GreeterClassLoader
's loadClass()
method will look in the greeters
directory,
load Cracker.class
, instantiate a new Cracker
object, and invoke greet()
on it.
Cracker
's greet()
method starts by instantiating a new Spoofed
.
This is where the plot thickens.
It turns out that there are two implementations of a class named Spoofed
.
The class file for the "trusted" implementation is sitting in the linking/ex8
directory,
where it will be discovered by the system class loader:
// On CD-ROM in file linking/ex8/Spoofed.java // Trusted version - when asked to give five, gives 5 public class Spoofed { private int secretValue = 42; public int giveMeFive() { return 5; } static { System.out.println("linking/ex8/Spoofed initialized."); } }
The trusted Spoofed
declares a private variable, named secretValue
, that is initialized to 42.
This private variable represents anything that needs to be kept secret:
a credit card number, a private key, an amount of e-cash, a reference to the current Policy
object, and so on.
Because the designers of this class didn't want the rest of the world to have access to the secret value,
they made the secretValue
variable private.
Only the methods of class Spoofed
can access secretValue
.
If you inspect the code to the trusted Spoofed
class,
you'll see that the designers of Spoofed didn't provide any method that reveals information about secretValue
.
The only method in Spoofed
, giveMeFive()
, returns the value 5.
But what if a maladjusted cracker was able to trick the virtual machine that
an instance of the trusted Spoofed
was really an instance of this class,
also named Spoofed
, which was written by the cracker:
// On CD-ROM in file linking/ex8/greeters/Spoofed.java // Malicious version - when asked to give five, this // version of Spoofed reveals secret_value public class Spoofed { private int secretValue = 100; public int giveMeFive() { return secretValue; } static { System.out.println("linking/ex8/greeters/Spoofed initialized."); } }
When this Spoofed
class's giveMeFive()
method is invoked, it returns secretValue
,
effectively rendering the value of the private variable public knowledge.
So which version of Spoofed
gets used by the Cracker
greeter?
Cracker
deviously attempts to use both.
First, Cracker
's greet()
method loads the malicious Spoofed
and
executes its greet()
method, just to get the feel of it:
Spoofed spoofed = new Spoofed(); System.out.println("secret val = " + spoofed.giveMeFive());
The Java compiler translates the new Spoofed()
expression into a new
bytecode instruction
that gives the index of a CONSTANT_Class_info
constant pool entry,
which represents a symbolic reference to Spoofed
.
When the virtual machine resolves this reference, it will ask the defining loader of Cracker
to load spoofed.
The defining loader of Cracker
is this version of GreeterClassLoader
,
which the cracker has had the opportunity to modify:
// On CD-ROM in file // linking/ex8/COM/artima/greeter/GreeterClassLoader.java package com.artima.greeter; import java.io.*; import java.util.Hashtable; public class GreeterClassLoader extends ClassLoader { // basePath gives the path to which this class // loader appends "/<typename>.class" to get the // full path name of the class file to load private String basePath; public GreeterClassLoader(String basePath) { this.basePath = basePath; } public synchronized Class loadClass(String className, boolean resolveIt) throws ClassNotFoundException { Class result; byte classData[]; // Check the loaded class cache result = findLoadedClass(className); if (result != null) { // Return a cached class return result; } // If Spoofed, don't delegate if (className.compareTo("Spoofed") != 0) { // Check with the system class loader try { result = super.findSystemClass(className); // Return a system class return result; } catch (ClassNotFoundException e) { } } // Don't attempt to load a system file except through // the primordial class loader if (className.startsWith("java.")) { throw new ClassNotFoundException(); } // Try to load it from the basePath directory. classData = getTypeFromBasePath(className); if (classData == null) { System.out.println("GCL - Can't load class: " + className); throw new ClassNotFoundException(); } // Parse it result = defineClass(className, classData, 0, classData.length); if (result == null) { System.out.println("GCL - Class format error: " + className); throw new ClassFormatError(); } if (resolveIt) { resolveClass(result); } // Return class from basePath directory return result; } private byte[] getTypeFromBasePath(String typeName) { FileInputStream fis; String fileName = basePath + File.separatorChar + typeName.replace('.', File.separatorChar) + ".class"; try { fis = new FileInputStream(fileName); } catch (FileNotFoundException e) { return null; } BufferedInputStream bis = new BufferedInputStream(fis); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { int c = bis.read(); while (c != -1) { out.write(c); c = bis.read(); } } catch (IOException e) { return null; } return out.toByteArray(); } }
To create this user-defined class loader,
the cracker took the GreeterClassLoader
from the linking/ex6
directory of the CD-ROM
(the one that overrides loadClass()
), and added one if statement:
// If Spoofed, don't delegate if (className.compareTo("Spoofed") != 0) { // Check with the system class loader try { result = super.findSystemClass(className); // Return a system class return result; } catch (ClassNotFoundException e) { } }
If the type name passed to loadClass()
is "Spoofed"
,
the loadClass()
method doesn't first delegate to the system class loader
before attempting to load the class in its custom way, by looking in the basePath
directory.
As a result, when the virtual machine asks this class loader (Cracker
's defining class loader) to load Spoofed
,
its loadClass()
doesn't delegate.
It just looks in the basePath
directory for Spoofed.class
,
where it finds and loads the definition of the malicious Spoofed
.
The application prints:
linking/ex8/greeters/Spoofed initialized.
The next statement in Cracker
's greet()
method invokes giveMeFive()
on the new Spoofed
instance and prints its return value:
secret val = 100
Having exercised the giveMeFive()
method and feeling smug,
Cracker
's greet()
method invokes a static method in a class named Delegated
,
which returns a reference of type Spoofed
:
spoofed = Delegated.getSpoofed();
The Java compiler transforms the Delegated.getSpoofed()
expression in the source code to
an invokestatic
bytecode instruction that gives the index of a CONSTANT_Methodref_info
entry in the constant pool.
To execute this instruction, the virtual machine must resolve the constant pool entry.
As the first step in resolving this symbolic reference to getSpoofed()
,
the virtual machine resolves the CONSTANT_Class_info
reference
whose index is given in the class_index
of the CONSTANT_Methodref_info
entry.
The CONSTANT_Class_info
entry is a symbolic reference to class Delegated
.
To resolve Cracker
's symbolic reference to Delegated
,
the virtual machine asks the defining class loader of Cracker
to load Delegated
.
Once again the virtual machine invokes GreeterClassLoader
's loadClass()
method,
this time passing in the name Delegated
.
However, because the requested name isn't "Spoofed"
,
the loadClass()
method goes ahead and delegates the load request to the system class loader.
Because Delegated.class
is sitting in the linking/ex8
directory,
the system class loader is able to load the class.
The system class loader is marked as the defining class loader for Delegated
,
and both the system class loader and the GreeterClassLoader
are marked as initiating class loaders.
Once Delegated
has been loaded,
the virtual machine completes the resolution of the CONSTANT_Methodref_info
and invokes the getSpoofed()
method.
Here's what Delegated
's getSpoofed()
method looks like:
// On CD-ROM in file linking/ex8/Delegated.java public class Delegated { public static Spoofed getSpoofed() { return new Spoofed(); } }
In Java source code, this looks quite innocuous.
The getSpoofed()
method merely instantiates yet another Spoofed
object and returns a reference to it.
Inside the Java virtual machine, however, a serious challenge to Java's guarantee of type safety is looming.
When the Java compiler encounters the new Spoofed()
expression in class Delegated
,
it generates a new
bytecode that gives the index of a CONSTANT_Class_info
that forms a symbolic reference to Spoofed
.
This is exactly what happened when the Java compiler encountered the new Spoofed()
expression in class Cracker
.
When the Java virtual machine executes this new
instruction,
just as when it executed the new
instruction in Cracker
's greet()
method,
it starts by resolving the symbolic reference to Spoofed
.
The virtual machine asks Delegated
's defining loader, which is the system class loader, to load Spoofed
.
Although this is the same process that the virtual machine used to resolve Cracker
's symbolic reference to Spoofed
,
the class loader to which the virtual machine makes its load request is different.
Because Cracker
's defining loader was GreeterClassLoader
,
the virtual machine asked GreeterClassLoader
to load Spoofed
.
But because Delegated
's defining loader was the system class loader,
the virtual machine now asks the system class loader to load Spoofed
.
Because the trusted version of Spoofed
is sitting in the linking/ex8
directory of the CD-ROM,
the system class loader is able to read in the bytes of the Spoofed.class
and pass them to defineClass()
.
What happens next depends on whether or not
the application is running in a Java virtual machine that adheres to the loading constraints
specified in the second edition of the Java virtual machine specification.
这里就是loading constraints起作用的地方
Assume for a moment that the application is running in an early Java virtual machine implementation that doesn't apply the loading constraints.
In that case, defineClass()
is able to define the type from the bytes read in from linking/ex2/Spoofed.class
.
The virtual machine creates a new instance of this trusted Spoofed
type.
Shortly thereafter, Delegated
's getSpoofed()
method returns a reference to the trusted Spoofed
object to its caller,
Cracker
's greet()
method.
Cracker
stores this reference in local variable spoofed
,
and proceeds to print out the value returned by invoking giveMeFive()
on spoofed
.
如果JVM还没有支持loading constraints
When Cracker.java
was compiled,
the Java compiler transformed this second giveMeFive()
invocation into
yet another invokevirtual
instruction that references a CONSTANT_Methodref_info
entry in the constant pool,
the symbolic reference to giveMeFive()
in Spoofed
.
When the virtual machine goes to resolve this symbolic reference, however, it discovers it has already been resolved.
The CONSTANT_Methodref_info
entry specified by the second giveMeFive()
invocation is the same as that specified by the first one,
which was resolved to the malicious Spoofed
's implementation of giveMeFive()
.
The virtual machine invokes the malicious Spoofed
method on the trusted Spoofed
object, and the application prints:
secret val = 42
Although this kind of type confusion attack was possible in many implementations of the Java virtual machine prior to version 1.2,
it usually couldn't be exploited in practice, because it requires the assistance of the class loader.
In this example, the cracker added an if statement to GreeterClassLoader
's loadClass()
method
that causes it to treat Spoofed
specially.
Were the cracker to attempt to instigate this kind of type confusion attack via an untrusted applet, he or she would run into trouble.
Untrusted applets are not allowed to create class loaders.
Thus, providing the designers of the class loaders in the application that loads applets into browsers did their jobs correctly,
the cracker would have no way to exploit this (former) weakness in Java's type safety guarantee.
In Java virtual machine implementations that check the loading constraints that are now part of the Java virtual machine specification,
the type confusion is not possible at all.
All virtual machines must now keep an internal list of loading constraints that must be met as types are loaded.
For example, when such a virtual machine resolves the CONSTANT_Methodref_info
entry in Cracker
' s constant pool
that forms a symbolic reference to the getSpoofed()
method of class Delegated
,
the virtual machine records a loading constraint.
Because Delegated
was defined by a different class loader than Cracker
,
and Delegated
's getSpoofed()
method returns a reference to a Spoofed
,
the virtual machine records the following constraint:
这里讲JVM支持loading constraints的情况
-
The type named
Spoofed
for which the system class loader (Delegated
defining class loader) is marked as an initiating loader must be the same type namedSpoofed
for whichGreeterClassLoader
(Cracker
's defining class loader) is marked as an initiating class loader.
This constraint is checked later,
when the virtual machine attempts to resolve the CONSTANT_Class_info
entry in Delegated
's constant pool
that forms a symbolic reference to class Spoofed
.
At that time, the virtual machine discovers that the constraint is violated.
The type named Spoofed
that is being loaded by the system class loader
is not the same type named Spoofed
that was loaded by GreeterClassLoader
.
As a result, the Java virtual machine throws a LinkageError
:
Exception in thread "main" java.lang.LinkageError: Class Spoofed violates loader constraints at java.lang.ClassLoader.defineClass0(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:422) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:10) at java.net.URLClassLoader.defineClass(URLClassLoader.java:248) at java.net.URLClassLoader.access$1(URLClassLoader.java:216) at java.net.URLClassLoader$1.run (URLClassLoader.java:197) at java.security.AccessController.doPrivileged (Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:191) at java.lang.ClassLoader.loadClass(ClassLoader.java:290) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:275) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at Delegated.getSpoofed(Delegated.java, Compiled Code) at Cracker.greet(Cracker.java:13) at Greet.main(Greet.java, Compiled Code)
Java's guarantee of type safety is a cornerstone of its security model.
Type safety means that programs are allowed to manipulate the memory
occupied by an object's instance variables on the heap only in ways that are defined by that object's class.
Likewise, type safety means that programs are allowed to manipulate the memory
occupied by a class's static variables in the method area only in ways that are defined by that class.
If the virtual machine can become confused about types, as demonstrated in this example,
malicious code can potentially look at or change non-public variables.
In addition, if malicious code could use a method defined in one version of a type to set an int
instance variable,
then use a method in another version of that type to interpret and return the value of the int
as an array,
the malicious code would in effect transform an int
to an array reference.
With this forged pointer, the malicious code could wreak all kinds of havoc.
Thus, it is important that Java's type safety guarantee be iron-clad.
The loading constraints ensure that, even in the presence of multiple namespaces, Java's type safety will be enforced at runtime.
On the CD-ROM
The CD-ROM contains the source code examples from this chapter in the linking
directory.
The Resources Page
For more information about the material presented in this chapter, visit the resources page:
http://www.artima.com/insidejvm/resources/


Health Wallet
Home
About
Sign up
Login
Donate
Login Form
Create
Already registered?
Sign In
Login
Not registered?
Create an account


|
Table 1
|
CMIP5 hindcast experiments with Earth System Models used in ... |
|
Table 2
|
Occurrences (% of total number of years) of individual and c ... |
|
Table 3
|
One- and two-year phase prediction skill in decadal hindcast ... |
|
Table 4
|
Same as Table 3, but for the TAG index |
|
Table 5
|
Same as Table 3, but for the detrended WPWP index |


--- layout: page title: Preservation permalink: /preservation/ ---
Last Updated: January 26, 2022
Durability is among Fulcrum's core values, and the foundation of our durability lies in our commitment to the preservation of the content which we publish. Our goal is to make publishing content on Fulcrum synonymous with adding it to the durable record of scholarship, as there is no preservation without access, and there is no access without preservation. This Preservation Statement expresses that commitment by answering the questions: "What can I expect a future scholar to encounter if they follow my citation to content I used on Fulcrum? How faithful should I expect a future representation of this content to be to what I see on Fulcrum today?"
In the interest of transparency and trustworthiness, this statement will summarize the decisions we have made and anticipate the decisions we will have to make in the future. We plan to revisit our preservation policies, and update this document accordingly, on an annual basis.
The Fulcrum Preservation Statement conforms to the University of Michigan Library's Digital Repository Services Digital Preservation Policy.
Digital preservation is often discussed in terms of technologies and file formats, but the Fulcrum team considers preservation primarily a commitment of time, attention, and active management of data and metadata. Through these commitments we will develop and maintain a variety of technological strategies and partnerships to achieve our commitments to durable publishing. As the future is unknown, successfully fulfilling our commitments requires a diversity of approaches to mitigate risk.
The digital preservation community has identified a number of basic strategies for digital preservation:
Fulcrum is employing a number of methods to achieve bit and migration preservation strategies, as detailed below. U-M Library is a sustaining member of the Software Preservation Network and is following with interest research in the area of sustainable emulation strategies, but we are not yet employing an emulation strategy at this time.
Fulcrum fulfills its preservation commitments through a strategy based on balancing local and distributed resources. By engaging in a number of partnerships, Fulcrum guards against the risk of technological failure, changes in institutional priorities, or inability to meet commitments at any one institution, thereby eliminating single points of failure and ensuring the long-term access to content published on Fulcrum.
The strength of Fulcrum's preservation commitment derives from its home within a Tier 1 research library which embodies preservation as core to its mission. As a result, Fulcrum adheres to the policies and practices of U-M Library, and content hosted on Fulcrum is preserved according to the same policies and practices, and with the same dedicated, committed effort, as all of U-M Library's digital materials.
U-M Library's institutional stance is strongly predisposed to migration strategies, which we enable via policies that restrict file formats at the point of ingest. Our file format guidelines are based on the recommendations of the Library of Congress and reflect the accepted best practices of the digital preservation community. Fulcrum's file format recommendations may place further restrictions based on compatibility with software tools, functionality on our platform, publishing industry standards, and accessibility. The open, published standards represented in these guidelines put us in the best position today to successfully migrate content to tomorrow's successor formats.
On those occasions where no open standard is available, or the de facto standard within a given discipline is a proprietary file format, Fulcrum may host the file with a commitment only to bit preservation. In those cases, when the file becomes obsolete, we may continue to host it as-is as an artifact of possible historical interest.
Fulcrum follows the principle of "Preservation is Access, Access is Preservation". Our Hyrax platform is backed by a Fedora 4 repository where preservation masters are managed in the U-M datacenter; masters are stored and backed up using enterprise-quality equipment and services provided by U-M Information Technology Services. This same repository is used for managing both the preservation masters and the access derivatives which are served to the browser in a user session, their relationship expressed explicitly via RDF metadata in our data model. In this way the same resources that maintain the access repository also benefit the preservation repository, and any problems that arise are more visible to the system administrators. Furthermore, by keeping content in our preservation repository, we are also committing to maintaining its access by readers.
Fulcrum has diversified its preservation portfolio through relationships with a number of other organizations, each with their own technological implementation and management structures. We have contracted with CLOCKSS, which is CRL-certified TRAC-compliant and introduces geographically distributed redundancy to our preservation solutions. Deposits into CLOCKSS must be configured on a per-collection basis; at the present time, our workflows cover the University of Michigan Press Ebook Collection. If you're interested in having your collection included in such an arrangement, please speak with the Fulcrum team.
U-M Library is a member of APTrust and routinely deposits all Fulcrum content into their cloud-based, consortially-governed service, providing further organizational and geographic redundancy for everything published on Fulcrum.
Michigan Publishing is a partner in the Mellon-funded Enhancing Services to Preserve New Forms of Scholarship grant administered by NYU, exploring methods with CLOCKSS and Portico to preserve the richness of digital media enhancements to ebooks on Fulcrum among other platforms.
The culmination of local and partnered preservation commitments, which place our content into storage networks distributed across multiple continents, actively managed by a range of mission-driven, non-profit consortia and partnerships (some of which have their own succession plans), mitigates the risk of catastrophic failure on any number of fronts, and helps ensure that the content published on Fulcrum today will remain in the scholarly record for many years to come.
Preservation always entails making choices about what to preserve. While Fulcrum strives to capture the most comprehensive record possible of a published work, finite resources of time, attention, and technology require the scrupulous application of those resources in order to achieve a preservation strategy that is most likely to succeed technologically while being comprehensible and useful to future generations.
Fulcrum's preservation commitment is focused on maintaining a "Version of Record" of the published work. Such a concept is intentionally malleable and subject to change as technologies and publishing conventions evolve, but is intended to capture the material that is essential to conveying the scholarly argument embodied in a work. At present, we are focused on preserving the text in EPUB3 format (or PDF/A, if EPUB is not available); any components embedded in the text (that would typically be included in an EPUB3 file), such as figures, tables, or time-based media; metadata, for the work as a whole, for the individual components, and relationships among the parts; and any supplemental materials that may be hosted on the platform. University of Michigan Library's strategy focuses on preserving all content in the form of its constituent files, migrating to new formats when both necessary and possible. All content is accompanied by metadata in schema that conform to current best practices in the Library community. Deposits into APTrust will include the full range of content that U-M Library commits to preserving. At present, CLOCKSS is supporting ingest and preservation support for EPUB3 and PDF/A, and we will be working to add support for media formats in the future.
U-M Library will conduct a review after a 10 year period to determine if objects hosted on Fulcrum should be retained and be subject to further, periodic, reviews thereafter. The goal of these reviews is to identify and possibly remove objects that have reached the end of their use and reuse life cycle, or have become unusable due to format obsolescence. U-M Library may conduct the review before 10 years if it identifies that a format is becoming obsolete. The retention review will be conducted by U-M Library and, whenever possible, by the partner who is responsible for its deposit.
In the eventuality that material is removed from Fulcrum due to retention review or for legal or contractual reasons, we will maintain tombstones with the metadata and a removal notice to which durable identifiers (DOIs, Handle System URLs) will continue to resolve. Where possible and applicable, the tombstone record will point to and/or resolve to the new location for the content.
Fulcrum's preservation commitments do not at present attempt to capture the context or user experience in which the materials described above are made available to the public. The following are considered out of scope:


--- layout: post title: Font Metrics in Java OR How, the hell, Should I Position This Font?! date: 2011-12-19 12:00:00 permalink: /2011/12/Font-Metrics-in-Java-OR-How-the-hell-Should-I-Position-This-Font disqus_url: http://evendanan.net/2011/12/Font-Metrics-in-Java-OR-How-the-hell-Should-I-Position-This-Font categories: [android] tags: [anysoftkeyboard, font] ---
I'm working on a new feature for AnySoftKeyboard, where it will 'hint' the user about what lays behind long-pressing a key.
I've decided that the best UX I can provide, is to draw a small character, at the bottom-right corner of the key, showing the long-press output, or "..." in case there are lots of them. It will probably look like this:
So, I had to figure out how to position the character there. Java/Android provides a nice service called FontMetrics, which provide general metrics on the font, like what is the tallest glyph (character), lowest glyph, etc.
Since the hint is very small, I had to make sure the position is precised. So I've dived into the definitions of those metrics,
and their values, and cooked up a small Android app which
visualizing the metrics, and since an image is worth 37.5 tweets, I give you a screenshot:
Here is FontMetrics in layman lingo:


Tests
Docs
city
name
phone
mail
Installation
Usage
API
npm-scripts
Docs
Installation
Usage
API
npm-scripts
Docs
Installation
Usage
API
npm-scripts
Docs
Installation
Usage
API
npm-scripts


Brendan Rodgers begins his Title-Race mind-games with Klopp…
by Biscan's BootsBrendan Rodgers has predictably painted his Leicester City side as the underdogs in this year’s title race, which in fairness, they are!
The Foxes have won eight on the bounce and are eight points behind us in second place in the Premier League table.
Crucially though, they’re now six points ahead of out of form Manchester City and as a result many believe they’ll be our closest challengers for top spot come May.
Rodgers, though, has separated Leicester from the quality of ourselves and City – claiming his only target is to continue ‘developing as a team’.
“I don’t think anyone expects us to be near the top,” he said, cited in the Express.
“After Manchester United won at Manchester City on Saturday, the caption came up about how far City are away from Liverpool.
“We respect that, we get on with our work and keep developing as a team.
“It’s just natural, Man City and Liverpool are both incredible teams.
“We know we are looking to improve and close the gap.
“We have finished ninth in the last two seasons but today we looked like a top team.”
Leicester are in the position they are because they deserve to be, first and foremost.
They have an excellent manager and many superb players including the Premier League’s most prolific striker Jamie Vardy.
Luckily for us, though, they face Manchester City in 11 days’ time, meaning one of them is going to drop points…
We then face the Foxes on Boxing Day following our return from Qatar in what is a potentially enormous fixture.


Dewan Negara observes moment’s silence for late senators
KUALA LUMPUR, Dec 9 — The Dewan Negara today observed a minute of silence and extended its condolences to family members of senator Datuk M. Sambanthan and senator Datuk Ong Chong Swen who died recently.
Sambanthan who was also Indian Progressive Front (IPF) president died of a heart attack on October 15. He was sworn in as a member of the Dewan Negara on September 25, 2017.
Ong, who was Wanita MCA national secretary-general and Selangor Wanita MCA chief, died on November 18. She was sworn in as a senator on February 19, 2018.
Dewan Negara president Tan Sri SA Vigneswaran, on behalf of the upper House, expressed sadness over the passing of the two senators which he described as a great loss to the country.
“All their deeds and contributions will always be remembered. May the family members be granted patience and strength in facing this test,” he said. — Bernama


pandas dataframe into LATEX PDF
2014-05-10
##pandasdataframeinto_PDF##
- Huge dataframes whihc goes for multiple A4 pages landscape is difficult to make in excel
- Alternative is use python pandas and convert the pandas dataframe into pdf thorugh latex or html, latex is promising for just printing
- Basically from ([1])(http://stackoverflow.com/questions/14380371/export-a-latex-table-from-pandas-dataframe) for convert dataframe into tex and this for converting tex into landscape pdf document
- the python script to make table text is as follows, It is mostly from 3rd answer [1] and bold column heading write python trick from
([3])(http://techoverflow.net/blog/2013/12/08/converting-pandas-dataframe-to-latex-tabular/)
import pandas as pd
data = pd.read_csv('PROJECT_EXPNDTR1.csv')
data2 = data[data['Consumbales'] == 1]
with open("my_table.tex", "w") as f:
f.write("\\begin{tabular}{" + " | ".join(["l"] * len(data2.columns)) + "}\n$
columnLabels = ["\\textbf{%s}" % label for label in data2.columns]
f.write ("%s\\\\\\hline\n" % " & ".join(columnLabels))
\\writes column labels
for i, row in data2.iterrows():
f.write(" & ".join([str(x) for x in row.values]) + " \\\\\n")
f.write("\\end{tabular}")
f.close()
- this script makes table tex file and it can be opened in texstudio to add with oter latex comand to make a A4 landscape pdf
- the landscape A4 page is generated by latex command from [2] and added with tricks of longtable, columns size specification and nice all page heading row with
\endhead
based on ([4])(http://tex.stackexchange.com/questions/11380/how-to-repeat-top-rows-column-headings-on-every-page), latex goes like this\documentclass{article} \usepackage[a4paper,margin=1in,landscape]{geometry} \usepackage{longtable} \usepackage{tabulary} \usepackage{blindtext} \begin{document} %% for adjust columns size\begin{longtable}{l | c | p{5cm} | p{2cm}| p{2cm} |p{2cm}| p{2cm}| p{2cm} |p{2cm} | p{2cm} | p{2cm}}%% %%%python gernated tex file content column heading%% \endhead %%%python gernated tex file content rows%% \end{longtable} \end{document}
- makes a A4 landscape table outof dataframe


file:///C:/My Documents - Opens a file or folder
on a local or network drive.
File transfer protocol
FTP users may authenticate themselves with a clear-text sign-in protocol, normally in the form of a
username and password.
- Can connect anonymously if the server is configured to allow it.
- Secure transmission that protects the username and password, and encrypts the content,
FTP is often secured with SSL/TLS (FTPS)
Hypertext Transfer Protocol
Defines a set of request methods to indicate the desired action to be performed for a given resource
The GET method requests a representation of the specified resource. Requests using GET should only retrieve data. The HEAD method asks for a response identical to that of a GET request, but without the response body. The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server The PUT method replaces all current representations of the target resource with the request payload. The DELETE method deletes the specified resource. The CONNECT method establishes a tunnel to the server identified by the target resource. The OPTIONS method is used to describe the communication options for the target resource. The TRACE method performs a message loop-back test along the path to the target resource. The PATCH method is used to apply partial modifications to a resource.
Hypertext Transfer Protocol Secure
Adds a layer of security on the data in transit through a secure socket layer (SSL) or transport layer security (TLS) protocol connection.
curl "https://mdn.mozillademos.org/my-handling-form-page" /
-H "content-type: application/x-www-form-urlencoded" /
-H "user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36" /
--data "user_name=miri^&user_email=miri^%^40gmail.com^&user_message=The best presentation ever" /
--compressed
Asynchronous JavaScript + XML(?)
Ajax is a set of Web technologies on the client side to create asynchronous Web applications
function reqListener () {
console.log(this.responseText);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.example.org/example.txt");
oReq.send();
var myImage = document.querySelector('img');
fetch('flowers.jpg').then(function(response) {
return response.blob();
}).then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
Two-way communication link between client and server
The browser sends a request to the server, indicating that it wants to switch protocols from HTTP to WebSocket. The client expresses its desire through the Upgrade header:
GET ws://echo.websocket.org/?encoding=text HTTP/1.1
Origin: http://websocket.org
Cookie: __utma=99as
Connection: Upgrade
Host: echo.websocket.org
Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw==
Upgrade: websocket
Sec-WebSocket-Version: 13
If the server understands the WebSocket protocol, it agrees to the protocol switch through the Upgrade header.
HTTP/1.1 101 WebSocket Protocol Handshake
Date: Fri, 10 Feb 2012 17:38:18 GMT
Connection: Upgrade
Server: Kaazing Gateway
Upgrade: WebSocket
Access-Control-Allow-Origin: http://websocket.org
Access-Control-Allow-Credentials: true
Sec-WebSocket-Accept: rLHCkw/SKsO9GAH/ZSFhBATDKrU=
Access-Control-Allow-Headers: content-type
At this point the HTTP connection breaks down and is replaced by the WebSocket connection over the same
underlying TCP/IP connection. The WebSocket connection uses the same ports as HTTP (80) and HTTPS (443),
by default.
HTTP/2 attempts to solve many of the shortcomings and inflexibilities of HTTP/1.1. Its many benefits include:
WebRTC (Web Real-Time Communications) is a technology which enables Web applications and sites to capture and optionally stream audio and/or video media, as well as to exchange arbitrary data between browsers without requiring an intermediary. The server only handles the introduction between the peers.
WebRTC Video Chathttps://github.com/mirih87/youtube-real-time-app
https://github.com/mirih87/webSocketsPresentation


The Wonderful Life of Alan Turing
English mathematician, computer scientist, logician, cryptanalyst, philosopher, and theoretical biologist. (1912 - 1954)
- Major contributor to the theory of computation. Famous for the "Turing Machine".
- During World War II, he served as a codebreaker for the UK. His contributions created a major positive impact in the war effort, via intercepting critical bits of military intelligence, which ulitimately resulted in a victory for the Allied Powers.
- Persecuted for being homosexual. He continues to serve as an inspiration for computer scientists and the LGBTQ+ community alike.


Notification Service
- Try setting custom message with unicode characters, for example: I ♥ ADF
- Try setting custom i18n resource key, for example: APP_LAYOUT.NOTIFICATIONS
- Try toggling the action button. Clicking the action within SnackBar should update the label under the toggle button.
- All elements support data-automation-id attributes and can be automated.
With action
{{ actionOutput }}
Custom Configuration
SnackBar Config
{{snackBarConfigObject}}
Quick Messages