java虚拟机可能是下面三个中的一个
1:抽象规范
2:一个具体实现
3:一个虚拟机实例
java虚拟机的生命周期
java虚拟机的天职就是:运行一个java程序.当一个java程序运行开始运行时,一个虚拟机实例就产生了.当一个计算机上同时运行三个java程序.则将产生三个java虚拟机实例.每个程序运行在自己的虚拟机里面,不会干扰.当程序运行完毕时,虚拟机将自动退出.
java虚拟机里面有两种线程,守护线程和非守护线程.守护线程是说java虚拟机自己的线程,如垃圾收集线程.而非守护线程则是java中运行的程序线程.当非守护线程都运行完了.java虚拟机将退出.
一个java虚拟机主要包括了:类转载子系统,运行时数据区,执行引擎,内存区等等.
运行时数据区------主要是:1 堆 2 方法区 3 java栈
堆和方法区对虚拟机实例中所有的对象都是共享的.而java栈区,是对每个线程都是独立的. 当一个class被载入到 classloader中时,会解析它的类型信息.把这些类型信息放到方法区,而把程序中运行的对象,放到堆区.当一个新线程被创建,就分配一个新的java栈.java栈中保存的,是方法中的一些变量,状态.java栈是由很多的java栈帧组成的.一个栈帧包含了一个方法运行的状态.当一个方法被执行的时候,就压入一个新的java栈帧到java栈中,方法返回的时候,就把栈帧弹出来,抛弃掉.
方法区
在java虚拟机中,被装载的类的类型信息和类的静态变量被存储在方法区这样的内存里面.java程序运行时,会查找这些个信息.方法区的大小,是动态的.也可以不是连续的.可自由在堆中分配.也可以由用户或者程序员指定.方法区可被垃圾收集.
方法区可以保存以下信息
这个类型的全限定名
直接超类的全限定名
是类类型还是接口
类型的访问修饰符
任何直接超类接口的全限定名的有序列表.
该类型的常量池
字段信息 类中声明的每个字段及其顺序 如字段名,类型.修饰符号.
方法信息:如方法名,返回类型.参数表列.修饰符号.字节码.操作数栈和栈帧中局部变量区大小等等
类静态变量
一个到类classloader的引用
一个到class类的引用
堆
用来存储运行时的对象实例
java栈
每启动一个新的线程.就会分配到一个java栈.java栈以帧为单位保存线程的运行状态.它有两种操作.入栈,出栈.
当一个方法被调用时,入栈,当一个方法返回时,出栈,或者当方法出现异常.也出栈.
栈帧
组成部分 局部变量区,操作数栈,帧数据区.
posted @
2006-04-05 18:25 dodoma 阅读(370) |
评论 (1) |
编辑 收藏
Eliminate obsolete object references消除过期的对象引用
When you switch from a language with manual memory management, such as C or C++, to agarbage-collected language, your job as a programmer is made much easier by the fact that your objects are automatically reclaimed when you're through with them. It seems almost like magic when you first experience it. It can easily lead to the impression that you don't have to think about memory management, but this isn't quite true.
java中也要注意内存管理
// Can you spot the "memory leak"?
public class Stack {
private Object[] elements;
private int size = 0;
public Stack(int initialCapacity) {
this.elements = new Object[initialCapacity];
}
Effective Java: Programming Language Guide
17
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size) {
Object[] oldElements = elements;
elements = new Object[2 * elements.length + 1];
System.arraycopy(oldElements, 0, elements, 0, size);
}
}
}
这里有一个内存泄漏
如果一个栈先是增长,然后再收缩,那么,从栈中弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,它们也不会被回收。这是因为,栈内部维护着对这些对象的过期引用(obsolete re f e re n c e)。所谓过期引用,是指永远也不会再被解除的引用
改正
public Object pop() {
if (size==0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null; // Eliminate obsolete reference清除引用
return result;
}
当程序员第一次被类似这样的问题困扰的时候,他们往往会过分小心:对于每一个对象引用,一旦程序不再用到它,就把它清空。这样做既没必要,也不是我们所期望的,因为这样做会把程序代码弄得很乱,并且可以想像还会降低程序的性能。“清空对象引用”这样的操作应该是一种例外,而不是一种规范行为。消除过期引用最好的方法是重用一个本来已经包含对象引用的变量,或者让这个变量结束其生命周期。如果你是在最紧凑的作用域范围内定义每一个变量(见第2 9条),则这种情形就会自然而然地发生。应该注意到,在目前的J V M实现平台上,仅仅退出定义变量的代码块是不够的,要想使引用消失,必须退出包含该变量的方法。
一般而言,只要一个类自己管理它的内存,程序员就应该警惕内存泄漏问题。一旦一个元素被释放掉,则该元素中包含的任何对象引用应该要被清空。
内存泄漏的另一个常见来源是缓存。一旦你把一个对象引用放到一个缓存中,它就很容易被遗忘掉,从而使得它不再有用之后很长一段时间内仍然留在缓存中
posted @
2006-03-31 16:35 dodoma 阅读(200) |
评论 (0) |
编辑 收藏
Avoid creating duplicate objects避免创建重复的对象
It is often appropriate to reuse a single object instead of creating a new functionally equivalent object each time it is needed. Reuse can be both faster and more stylish. An object can always be reused if it is immutable
String s = new String("silly"); // DON'T DO THIS!
String s = "No longer silly";//do this
In addition to reusing immutable objects, you can also reuse mutable objects that you know will not be modified. Here is a slightly more subtle and much more common example of what not to do, involving mutable objects that are never modified once their values have been computed:
除了重用非可变的对象之外,对于那些已知不会被修改的可变对象,你也可以重用它们。
such as
public class Person {
private final Date birthDate;
// Other fields omitted
public Person(Date birthDate) {
this.birthDate = birthDate;
}
// DON'T DO THIS!
public boolean isBabyBoomer() {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >= 0 &&
birthDate.compareTo(boomEnd) < 0;
}
}
改良的版本.
The isBabyBoomer method unnecessarily creates a new Calendar, TimeZone, and two Date instances each time it is invoked. The version that follows avoids this inefficiency with a static initializer:
class Person {
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
/**
* The starting and ending dates of the baby boom.
*/
private static final Date BOOM_START;
private static final Date BOOM_END;
static {
Calendar gmtCal =
Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0 &&
birthDate.compareTo(BOOM_END) < 0;
}
}
。一个适配器是指这样一个对象:它把功能委
托给后面的一个对象,从而为后面的对象提供一个可选的接口。由于适配器除了后面的对象之外,没有其他的状态信息,所以针对某个给定对象的特定适配器而言,它不需要创建多个适配器实例。
This item should not be misconstrued to imply that object creation is expensive and should be avoided. On the contrary, the creation and reclamation of small objects whose constructors do little explicit work is cheap, especially on modern JVM implementations. Creating additional objects to enhance the clarity, simplicity, or power of a program is generally a good thing.
Conversely, avoiding object creation by maintaining your own object pool is a bad idea unless the objects in the pool are extremely heavyweight. A prototypical example of an object that does justify an object pool is a database connection. The cost of establishing the connection is sufficiently high that it makes sense to reuse these objects. Generally speaking, however, maintaining your own object pools clutters up your code, increases memory footprint, and harms performance. Modern JVM implementations have highly optimized garbage collectors that easily outperform such object pools on lightweight objects.
posted @
2006-03-31 15:19 dodoma 阅读(199) |
评论 (0) |
编辑 收藏
Enforce noninstantiability with a private constructor用一个私有的构造函数来让一个类不可以实例化
Occasionally you'll want to write a class that is just a grouping of static methods and static fields.有时候,你想写一个类,只是需要他提供了一系列的函数操作等,而不想让它实例化.如:java.lang.Math or java.util.Arrays.
但是如果你不提供构造函数,编译器会自动添加一个.
所以必须提供一个.此时,把构造函数设置为private.就可以达到目的.
一般用与工具类.
// Noninstantiable utility class
public class UtilityClass {
// Suppress default constructor for noninstantiability
private UtilityClass() {
// This constructor will never be invoked
}
... // Remainder omitted
}
由于private的构咱函数,该类不能被实例化.同时.不能被继承了.
posted @
2006-03-30 22:22 dodoma 阅读(210) |
评论 (0) |
编辑 收藏
Enforce the singleton property with a private constructor(用私有构造函数执行单例singlton)
A singleton is simply a class that is instantiated exactly once [Gamma98, p. 127].如数据库资源等.
There are two approaches to implementing singletons. Both are based on keeping the
constructor private and providing a public static member to allow clients access to the sole
instance of the class. In one approach, the public static member is a final field:
// Singleton with final field
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {
...
}
... // Remainder omitted
}
1:构造函数私有
2:提供一个静态static的final成员
The private constructor is called only once, to initialize the public static final field
Elvis.INSTANCE.
Exactly one Elvis instance will exist once the Elvis class is initialized—no more,
no less. Nothing that a client does can change this.
In a second approach, a public static factory method is provided instead of the public static final field:
// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() {
...
}
public static Elvis getInstance() {
return INSTANCE;
}
... // Remainder omitted
}
用静态方法返回,而不是直接返回一个实例.
如果对对象序列化,要做多一点工作.如
To make a singleton class serializable (Chapter 10), it is not sufficient merely to add
implements Serializable to its declaration. To maintain the singleton guarantee, you must
also provide a readResolve method (Item 57). Otherwise, each deserialization of a serialized instance will result in the creation of a new instance, 否则,经过对象反序列化后,会导致创建了一个新的对象.leading, in the case of our example, to spurious Elvis sightings. To prevent this, add the following readResolve method to the Elvis class:
// readResolve method to preserve singleton property
private Object readResolve() throws ObjectStreamException {
/*
* Return the one true Elvis and let the garbage collector
* take care of the Elvis impersonator.
*/
return INSTANCE;
}
posted @
2006-03-30 17:24 dodoma 阅读(237) |
评论 (0) |
编辑 收藏
Consider providing static factory methods instead of
constructors 考虑以静态工厂方法取代构造函数
The normal way for a class to allow a client to obtain an instance is to provide a public
constructor.
A class can provide a public static factory method, which is simply
a static method that returns an instance of the class
such as
public static Boolean valueOf(boolean b) {
return (b ? Boolean.TRUE : Boolean.FALSE);
}
advantages
1:One advantage of static factory methods is that, unlike constructors, they have names.
一个类静态工厂方法是有名字的.If the parameters to a constructor do not, in and of themselves, describe the object being returned, a static factory with a well-chosen name can make a class easier to use and the resulting client code easier to read. 如BigInteger(int, int,Random)只知道new了一个BigInteger对象,而BigInteger.probablePrime()能说明返回的可能是一个素数对象.另外,如果一个构造函数仅仅由于参数顺序不同而意思也不同.静态工厂方法就更加有用了.它更能说明函数的意思.因为它有一个名字.
the reason are : If the parameters to a constructor do not, describe the object being
returned, a static factory with a well-chosen name can make a class easier to use and the
resulting client code easier to read.
2:A second advantage of static factory methods is that, unlike constructors, they are not
required to create a new object each time they're invoked.每次请求时,不需要重新创建一个对象----单例的意思.这可以在任何时刻控制这个对象,同时在比较的时候也不需要用equals而用= =就可以解决了.
3:A third advantage of static factory methods is that, unlike constructors, they can return
an object of any subtype of their return type.可以返回一个原返回类型的子类型对象.
One application of this flexibility is that an API can return objects without making their
classes public.Hiding implementation classes in this fashion can lead to a very compact API.这种灵活性的一个应用是,一个A P I可以返回一个对象,同时又不使该对象的类成为公有的。以这种方式把具体的实现类隐藏起来,可以得到一个非常简洁的A P I。这项技术非常适合
于基于接口的框架结构,因为在这样的框架结构中,接口成为静态工厂方法的自然返回类型
sample:
// Provider framework sketch
public abstract class Foo {
// Maps String key to corresponding Class object
private static Map implementations = null;
// Initializes implementations map the first time it's called
private static synchronized void initMapIfNecessary() {
if (implementations == null) {
implementations = new HashMap();
// Load implementation class names and keys from
// Properties file, translate names into Class
// objects using Class.forName and store mappings.
...
}
}
public static Foo getInstance(String key) {
initMapIfNecessary();
Class c = (Class) implementations.get(key);
if (c == null)
return new DefaultFoo();
try {
return (Foo) c.newInstance();
} catch (Exception e) {
return new DefaultFoo();
}
}
}
公有的静态工厂方法所返回的对象的类不仅可以是非公有的,而且该类可以随着每次调用
而发生变化,这取决于静态工厂方法的参数值。只要是已声明的返回类型的子类型,都是允
许的。而且,为了增强软件的可维护性,返回对象的类也可以随着不同的发行版本而不同。
disadvantages:
1:The main disadvantage of static factory methods is that classes without public or protected constructors cannot be subclassed.
类如果不含公有的或者受保护的构造函数,就不能被子类化。对于公有的静态工厂所返回的非公有类,也同样如此
2:A second disadvantage of static factory methods is that they are not readily distinguishable from other static methods.
In summary, static factory methods and public constructors both have their uses, and it pays to understand their relative merits. Avoid the reflex to provide constructors without first considering static factories because static factories are often more appropriate. If you've weighed the two options and nothing pushes you strongly in either direction, it's probably best to provide a constructor simply because it's the norm.
posted @
2006-03-30 17:08 dodoma 阅读(217) |
评论 (0) |
编辑 收藏