??xml version="1.0" encoding="utf-8" standalone="yes"?> 引言 Java的堆是一个运行时数据?SPAN lang=EN-US>,cȝ实例(对象)从中分配I间?SPAN lang=EN-US>Java虚拟?SPAN lang=EN-US>(JVM)的堆中储存着正在q行的应用程序所建立的所有对象,q些对象通过new?SPAN lang=EN-US>newarray?SPAN lang=EN-US>anewarray?SPAN lang=EN-US>multianewarray{指令徏立,但是它们不需要程序代码来昑ּ地释放。一般来_堆的是由垃圾回收 来负责的Q尽?SPAN lang=EN-US>JVM规范q不要求Ҏ的垃圑֛收技术,甚至Ҏ׃需要垃圑֛Ӟ但是׃内存的有限性,JVM在实现的时候都有一个由垃圾回收所理的堆。垃圑֛收是一U动态存储管理技术,它自动地释放不再被程序引用的对象Q按照特定的垃圾攉法来实现资源自动回收的功能?SPAN lang=EN-US> 垃圾攉的意?SPAN lang=EN-US> ?SPAN lang=EN-US>C++中,对象所占的内存在程序结束运行之前一直被占用Q在明确释放之前不能分配l其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时Q该内存便成为垃圾?SPAN lang=EN-US>JVM的一个系lU程会自动释放该内存块。垃圾收集意味着E序不再需要的对象?SPAN lang=EN-US>"无用信息"Q这些信息将被丢弃。当一个对象不再被引用的时候,内存回收它占领的I间Q以便空间被后来的新对象使用。事实上Q除了释放没用的对象Q垃圾收集也可以清除内存记录片。由于创建对象和垃圾攉器释放丢弃对象所占的内存I间Q内存会出现片。碎片是分配l对象的内存块之间的I闲内存z。碎片整理将所占用的堆内存Ud堆的一端,JVM整理出的内存分配给新的对象?SPAN lang=EN-US> 垃圾攉能自动释攑ֆ存空_减轻~程的负担。这?SPAN lang=EN-US>Java 虚拟机具有一些优炏V首先,它能使编E效率提高。在没有垃圾攉机制的时候,可能要花许多旉来解决一个难懂的存储器问题。在?SPAN lang=EN-US>Java语言~程的时候,靠垃圾收集机制可大大~短旉。其ơ是它保护程序的完整?SPAN lang=EN-US>, 垃圾攉?SPAN lang=EN-US>Java语言安全性策略的一个重要部份?SPAN lang=EN-US> 垃圾攉的一个潜在的~点是它的开销影响E序性能?SPAN lang=EN-US>Java虚拟机必追t运行程序中有用的对?SPAN lang=EN-US>, 而且最l释放没用的对象。这一个过E需要花费处理器的时间。其ơ垃圾收集算法的不完备性,早先采用的某些垃圾收集算法就不能保证100%攉到所有的废弃内存。当焉着垃圾攉法的不断改q以及Ygq行效率的不断提升,q些问题都可以迎刃而解?SPAN lang=EN-US> 垃圾攉的算法分?SPAN lang=EN-US> Java语言规范没有明确地说?SPAN lang=EN-US>JVM使用哪种垃圾回收法Q但是Q何一U垃圾收集算法一般要?SPAN lang=EN-US>2件基本的事情Q(1Q发现无用信息对象;Q?SPAN lang=EN-US>2Q回收被无用对象占用的内存空_使该I间可被E序再次使用?SPAN lang=EN-US> 大多数垃圑֛收算法用了栚w(root set)q个概念Q所谓根集就量正在执行的JavaE序可以讉K的引用变量的集合(包括局部变量、参数、类变量)Q程序可以用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可辄对象都是zd对象Q它们不能作为垃圾被回收Q这也包括从栚w间接可达的对象。而根集通过L路径不可辄对象W合垃圾攉的条Ӟ应该被回收。下面介l几个常用的法?SPAN lang=EN-US> 1?SPAN style="FONT: 7pt 'Times New Roman'"> 引用计数?/SPAN>(Reference Counting Collector) 引用计数法是唯一没有使用栚w的垃圑֛收的法,该算法用引用计数器来区分存zd象和不再使用的对象。一般来_堆中的每个对象对应一个引用计数器。当每一ơ创Z个对象ƈ赋给一个变量时Q引用计数器|ؓ1。当对象被赋lQ意变量时Q引用计数器每次?SPAN lang=EN-US>1当对象出了作用域?SPAN lang=EN-US>(该对象丢弃不再?SPAN lang=EN-US>)Q引用计数器?SPAN lang=EN-US>1Q一旦引用计数器?SPAN lang=EN-US>0Q对象就满了垃圾收集的条g?/SPAN> Z引用计数器的垃圾攉器运行较快,不会长时间中断程序执行,适宜地必?实时q行的程序。但引用计数器增加了E序执行的开销Q因为每ơ对象赋l新的变量,计数器加1Q而每ơ现有对象出了作用域生,计数器减1?/SPAN> 2?SPAN lang=EN-US style="COLOR: red">tracing法(Tracing Collector) tracing法是ؓ了解军_用计数法的问题而提出,它用了栚w的概c基?SPAN lang=EN-US>tracing法的垃圾收集器从根集开始扫描,识别出哪些对象可达,哪些对象不可达,q用某种方式标记可达对象Q例如对每个可达对象讄一个或多个位。在扫描识别q程中,Ztracing法的垃圾收集也UCؓ标记和清?SPAN lang=EN-US>(mark-and-sweep)垃圾攉?SPAN lang=EN-US>. 3?SPAN lang=EN-US style="COLOR: red">compacting法(Compacting Collector) Z解决堆碎片问题,Ztracing的垃圑֛收吸收了Compacting法的思想Q在清除的过E中Q算法将所有的对象Ud堆的一端,堆的另一端就变成了一个相ȝI闲内存区,攉器会对它Ud的所有对象的所有引用进行更斎ͼ使得q些引用在新的位|能识别原来 的对象。在ZCompacting法的收集器的实CQ一般增加句柄和句柄表。 4?SPAN lang=EN-US style="COLOR: red">copying法(Coping Collector) 该算法的提出是ؓ了克服句柄的开销和解军_片的垃圑֛收。它开始时把堆分成 一个对?面和多个I闲面, E序从对象面为对象分配空_当对象满了,Zcoping法的垃?攉׃栚w中扫描活动对象,q将每个 zd对象复制到空闲面(使得zd对象所占的内存之间没有I闲z?SPAN lang=EN-US>)Q这L闲面变成了对象面Q原来的对象面变成了I闲面,E序会在新的对象面中分配内存?SPAN lang=EN-US> 一U典型的Zcoping法的垃圑֛收是stop-and-copy法Q它堆分成对象面和I闲区域面,在对象面与空闲区域面的切换过E中Q程序暂停执行?SPAN lang=EN-US> 5?SPAN lang=EN-US style="COLOR: red">generation法(Generational Collector) 6?SPAN lang=EN-US style="COLOR: red">adaptive法(Adaptive Collector) 在特定的情况下,一些垃圾收集算法会优于其它法。基?SPAN lang=EN-US>Adaptive法的垃圾收集器是监控当前堆的使用情况Qƈ选择适当法的垃圾收集器?SPAN lang=EN-US> 透视Java垃圾回收 1、命令行参数透视垃圾攉器的q行 2、?SPAN lang=EN-US>System.gc()可以不管JVM使用的是哪一U垃圑֛收的法Q都可以hJava的垃圑֛收。在命o行中有一个参?SPAN lang=EN-US>-verbosegc可以查看Java使用的堆内存的情况,它的格式如下Q?SPAN lang=EN-US> class TestGC class Chair {
public class TestTry extends Exception
{
static boolean f=false;
static int sum=0;
static int created=0;
static int i=0;
TestTry()
{
i=created++;
if(created>=299) f=true;
}
public void finalize()
{
sum++;
}
public static void main(String[] args)
{
while(!TestTry.f)
{
try{
throw new TestTry();
}catch(Exception e){}
finally{
System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");
}
}
//System.out.println("Creat "+TestTry.created+" TestTry, "+TestTry.sum+" has been finalized!");
}
}
q个是我在测试在try语句抛出异常后,在try语句中徏立的对象是否会调用自w的l止函数时发现的Q这里有个奇怪的现象在if(created>=299) f=true;q条语句中,如果把条件created>=299改ؓ>=?99更大的数Q你会发现System.out.println("Creat "+TestTry.i+" TestTry, "+TestTry.sum+" has been finalized!");q条语句的输出的l果q不是你预想的那P输出判断的数?1的行敎ͼQ而只是显C最后的三百行。那么在q之前抛出的异常上哪里去了呢Q难道说Java只处理最后抛出的三百的异怹Q?BR>
stop-and-copy垃圾攉器的一个缺h攉器必d制所有的zd对象Q这增加了程序等待时_q是coping法低效的原因。在E序设计中有q样的规律:多数对象存在的时间比较短Q少数的存在旉比较ѝ因此,generation法堆分成两个或多个,每个子堆作ؓ对象的一?SPAN lang=EN-US>(generation)。由于多数对象存在的旉比较短,随着E序丢弃不用的对象Q垃圾收集器从最q轻的子堆中攉q些对象。在分代式的垃圾攉器运行后Q上ơ运行存zM来的对象Ud下一最高代的子堆中Q由于老一代的子堆不会l常被回Ӟ因而节省了旉?SPAN lang=EN-US>
java -verbosegc classfile
可以看个例子Q?/SPAN>
{
public static void main(String[] args)
{
new TestGC();
System.gc();
System.runFinalization();
}
}
在这个例子中Q一个新的对象被创徏Q由于它没有使用Q所以该对象q速地变ؓ可达Q程序编译后Q执行命令: java -verbosegc TestGC 后结果ؓQ?SPAN lang=EN-US>
[Full GC 168K->97K(1984K), 0.0253873 secs]
机器的环境ؓQ?SPAN lang=EN-US>Windows 2000 + JDK
2?SPAN lang=EN-US>finalizeҎ透视垃圾攉器的q行
?SPAN lang=EN-US>JVM垃圾攉器收集一个对象之?Q一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下Q?SPAN lang=EN-US>Java提供了缺省机制来l止化该对象心释放资源,q个Ҏ是finalizeQ)。它的原型ؓQ?SPAN lang=EN-US>
protected void finalize() throws Throwable
?SPAN lang=EN-US>finalize()Ҏq回之后Q对象消失,垃圾攉开始执行。原型中?SPAN lang=EN-US>throws Throwable表示它可以抛ZQ何类型的异常?SPAN lang=EN-US>
之所以要使用finalize()Q是׃有时需要采取与Java的普通方法不同的一U方法,通过分配内存来做一些具?SPAN lang=EN-US>C风格的事情。这主要可以通过"固有Ҏ"来进行,它是?SPAN lang=EN-US>Java里调用非JavaҎ的一U方式?SPAN lang=EN-US>C?SPAN lang=EN-US>C++是目前唯一获得固有Ҏ支持的语a。但׃它们能调用通过其他语言~写的子E序Q所以能够有效地调用M东西。在?SPAN lang=EN-US>Java代码内部Q也许能调用C?SPAN lang=EN-US>malloc()pd函数Q用它分配存储空间。而且除非调用?SPAN lang=EN-US>free()Q否则存储空间不会得到释放,从而造成内存"漏洞"的出现。当Ӟfree()是一?SPAN lang=EN-US>C?SPAN lang=EN-US>C++函数Q所以我们需要在finalize()内部的一个固有方法中调用它。也是说我们不能过多地使用finalize()Q它q不是进行普通清除工作的理想场所?SPAN lang=EN-US>
在普通的清除工作中,为清除一个对象,那个对象的用户必d希望q行清除的地点调用一个清除方法。这?SPAN lang=EN-US>C++"破坏?SPAN lang=EN-US>"的概늨有抵触。在C++中,所有对象都会破坏(清除Q。或者换句话_所有对象都"应该"破坏。若?SPAN lang=EN-US>C++对象创徏成一个本地对象,比如在堆栈中创徏Q在Java中是不可能的Q,那么清除或破坏工作就会在"l束花括?SPAN lang=EN-US>"所代表的、创个对象的作用域的末尾q行。若对象是用new创徏的(cM?SPAN lang=EN-US>JavaQ,那么当程序员调用C++?SPAN lang=EN-US>delete命oӞJava没有q个命oQ,׃调用相应的破坏器。若E序员忘CQ那么永q不会调用破坏器Q我们最l得到的是一个内?SPAN lang=EN-US>"漏洞"Q另外还包括对象的其他部分永q不会得到清除?SPAN lang=EN-US>
相反Q?SPAN lang=EN-US>Java不允许我们创建本圎ͼ局部)对象--无论如何都要使用new。但?SPAN lang=EN-US>Java中,没有"delete"命o来释攑֯象,因ؓ垃圾攉器会帮助我们自动释放存储I间。所以如果站在比较简化的立场Q我们可以说正是׃存在垃圾攉机制Q所?SPAN lang=EN-US>Java没有破坏器。然而,随着以后学习的深入,׃知道垃圾攉器的存在q不能完全消除对破坏器的需要,或者说不能消除对破坏器代表的那U机制的需要(而且l对不能直接调用finalize()Q所以应量避免用它Q。若希望执行除释攑֭储空间之外的其他某种形式的清除工作,仍然必须调用Java中的一个方法。它{h?SPAN lang=EN-US>C++的破坏器Q只是没后者方ѝ?SPAN lang=EN-US>
下面q个例子向大家展CZ垃圾攉所l历的过E,q对前面的陈q进行了ȝ?SPAN lang=EN-US>
static boolean gcrun = false;
static boolean f = false;
static int created = 0;
static int finalized = 0;
int i;
Chair() {
i = ++created;
if(created == 47)
System.out.println("Created 47");
}
protected void finalize() {
if(!gcrun) {
gcrun = true;
System.out.println("Beginning to finalize after " + created + " Chairs have been created");
}
if(i == 47) {
System.out.println("Finalizing Chair #47, " +"Setting flag to stop Chair creation");
f = true;
}
finalized++;
if(finalized >= created)
System.out.println("All " + finalized + " finalized");
}
}
public class Garbage {
public static void main(String[] args) {
if(args.length == 0) {
System.err.println("Usage: \n" + "java Garbage before\n or:\n" + "java Garbage after");
return;
}
while(!Chair.f) {
new Chair();
new String("To take up space");
}
System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created +
", total finalized = " + Chair.finalized);
if(args[0].equals("before")) {
System.out.println("gc():");
System.gc();
System.out.println("runFinalization():");
System.runFinalization();
}
System.out.println("bye!");
if(args[0].equals("after"))
System.runFinalizersOnExit(true);
}
}
上面q个E序创徏了许?SPAN lang=EN-US>Chair对象Q而且在垃圾收集器开始运行后的某些时候,E序会停止创?SPAN lang=EN-US>Chair。由于垃圾收集器可能在Q何时间运行,所以我们不能准知道它在何时启动。因此,E序用一个名?SPAN lang=EN-US>gcrun的标记来指出垃圾攉器是否已l开始运行。利用第二个标记fQ?SPAN lang=EN-US>Chair可告?SPAN lang=EN-US>main()它应停止对象的生成。这两个标记都是?SPAN lang=EN-US>finalize()内部讄的,它调用于垃圾攉期间。另两个static变量--created以及finalized--分别用于跟踪已创建的对象数量以及垃圾攉器已q行完收ַ作的对象数量。最后,每个Chair都有它自qQ非staticQ?SPAN lang=EN-US>int iQ所以能跟踪了解它具体的~号是多。编号ؓ47?SPAN lang=EN-US>Chairq行完收ַ作后Q标C设ؓtrueQ最l结?SPAN lang=EN-US>Chair对象的创E。(关于q个例子的更具体的分析和说明请参看?SPAN lang=EN-US>Java~程思想》的W四章)
关于垃圾攉的几点补?/B>
l过上述的说明,可以发现垃圾回收有以下的几个特点Q?SPAN lang=EN-US>
Q?SPAN lang=EN-US>1Q垃圾收集发生的不可预知性:׃实现了不同的垃圾攉法和采用了不同的收集机Ӟ所以它有可能是定时发生Q有可能是当出现pȝI闲CPU资源时发生,也有可能是和原始的垃圾收集一P{到内存消耗出现极限时发生Q这与垃圾收集器的选择和具体的讄都有关系?SPAN lang=EN-US>
Q?SPAN lang=EN-US>2Q垃圾收集的_性:主要包括2 个方面:Q?SPAN lang=EN-US>aQ垃圾收集器能够_标记zȝ的对象;Q?SPAN lang=EN-US>bQ垃圾收集器能够_地定位对象之间的引用关系。前者是完全地回收所有废弃对象的前提Q否则就可能造成内存泄漏。而后者则是实现归q和复制{算法的必要条g。所有不可达对象都能够可靠地得到回收Q所有对象都能够重新分配Q允许对象的复制和对象内存的~ƈQ这样就有效地防止内存的支离破碎。(3Q现在有许多U不同的垃圾攉器,每种有其法且其表现各异Q既有当垃圾攉开始时停止应用程序的q行Q又有当垃圾攉开始时也允许应用程序的U程q行Q还有在同一旉垃圾攉多线E运行?SPAN lang=EN-US>
Q?SPAN lang=EN-US>4Q垃圾收集的实现和具体的JVM 以及JVM的内存模型有非常紧密的关pR不同的JVM 可能采用不同的垃圾收集,?SPAN lang=EN-US>JVM 的内存模型决定着?SPAN lang=EN-US>JVM可以采用哪些cd垃圾攉。现在,HotSpot pdJVM中的内存pȝ都采用先q的面向对象的框架设计,q得该pdJVM都可以采用最先进的垃圾收集?SPAN lang=EN-US>
Q?SPAN lang=EN-US>5Q随着技术的发展Q现代垃圾收集技术提供许多可选的垃圾攉器,而且在配|每U收集器的时候又可以讄不同的参敎ͼq就使得Ҏ不同的应用环境获得最优的应用性能成ؓ可能?SPAN lang=EN-US>
针对以上特点Q我们在使用的时候要注意Q?SPAN lang=EN-US>
Q?SPAN lang=EN-US>1Q不要试囑֎假定垃圾攉发生的时_q一切都是未知的。比如,Ҏ中的一个时对象在Ҏ调用完毕后就变成了无用对象,q个时候它的内存就可以被释放?SPAN lang=EN-US>
Q?SPAN lang=EN-US>2Q?SPAN lang=EN-US>Java中提供了一些和垃圾攉打交道的c,而且提供了一U强行执行垃圾收集的Ҏ--调用System.gc()Q但q同h个不定的方法?SPAN lang=EN-US>Java 中ƈ不保证每ơ调用该Ҏ׃定能够启动垃圾收集,它只不过会向JVM发出q样一个申P到底是否真正执行垃圾攉Q一切都是个未知数?SPAN lang=EN-US>
Q?SPAN lang=EN-US>3Q挑选适合自己的垃圾收集器。一般来_如果pȝ没有Ҏ和苛ȝ性能要求Q可以采?SPAN lang=EN-US>JVM的缺省选项。否则可以考虑使用有针Ҏ的垃圾攉器,比如增量攉器就比较适合实时性要求较高的pȝ之中。系l具有较高的配置Q有比较多的闲置资源Q可以考虑使用q行标记/清除攉器?SPAN lang=EN-US>
Q?SPAN lang=EN-US>4Q关键的也是难把握的问题是内存泄漏。良好的~程习惯和严谨的~程态度永远是最重要的,不要让自q一个小错误D内存出现大漏z?SPAN lang=EN-US>
Q?SPAN lang=EN-US>5Q尽早释放无用对象的引用。大多数E序员在使用临时变量的时候,都是让引用变量在退出活动域(scope)后,自动讄?SPAN lang=EN-US>nullQ暗C垃圾收集器来收集该对象Q还必须注意该引用的对象是否被监听,如果有,则要L监听器,然后再赋I倹{?SPAN lang=EN-US>
l束?/B>
一般来_Java开发h员可以不重视JVM中堆内存的分配和垃圾处理攉Q但是,充分理解Java的这一Ҏ可以让我们更有效地利用资源。同时要注意finalize()Ҏ?SPAN lang=EN-US>Java的缺省机Ӟ有时为确保对象资源的明确释放Q可以编写自qfinalizeҎ?SPAN lang=EN-US>
You are given a String[] cityMap representing the layout of a city. The city consists of blocks. The first element of cityMap represents the first row of blocks, etc. A 'B' character indicates a location where there is a bus stop. There will be exactly one 'X' character, indicating your location. All other characters will be '.'. You are also given an int walkingDistance, which is the maximum distance you are willing to walk to a bus stop. The distance should be calculated as the number of blocks vertically plus the number of blocks horizontally. Return the number of bus stops that are within walking distance of your current location.
Definition
Class:BusStops
Method:countStops
Parameters:String[], int
Returns:int
Method signature:int countStops(String[] cityMap, int walkingDistance)
(be sure your method is public)
Constraints
-cityMap will contain between 1 and 50 elements, inclusive.
-Each element of cityMap will contain between 1 and 50 characters, inclusive.
-Each element of cityMap will contain the same number of characters.
-Each character of each element of cityMap will be 'B', 'X', or '.'.
-There will be exactly one 'X' character in cityMap.
-walkingDistance will be between 1 and 100, inclusive.
Examples
0)
{"...B.",
".....",
"..X.B",
".....",
"B...."}
3
Returns: 2
You can reach the bus stop at the top (3 units away), or on the right (2 units away). The one in the lower left is 4 units away, which is too far.
1)
{"B.B..",
".....",
"B....",
".....",
"....X"}
8
Returns: 3
A distance of 8 can get us anywhere on the map, so we can reach all 3 bus stops.
2)
{"BBBBB",
"BB.BB",
"B.X.B",
"BB.BB",
"BBBBB"}
1
Returns: 0
Plenty of bus stops, but unfortunately we cannot reach any of them.
3)
{"B..B..",
".B...B",
"..B...",
"..B.X.",
"B.B.B.",
".B.B.B"}
3
Returns: 7
Problem Statement
When a stone is thrown across water, sometimes it will land on the water and bounce rather than falling in right away. Suppose that a stone is thrown a distance of n. On each successive bounce it will travel half the distance as the previous bounce (rounded down to the nearest integer). When it can not travel any further, it falls into the water. If, at any point, the stone lands on an obstruction rather than water, it will not bounce, but will simply deflect and fall into the water. Please look at the figure for further clarification (with black, red and green cells representing banks, obstructions and free water respectively). So, if the stone is thrown a distance 7, it will bounce and travel a distance of 3, then finally a distance of 1, having travelled a total distance of 11 (the green path in the figure). If a stone is thrown a distance of 8, it will reach the opposite bank, and if thrown at distances of 2 or 6 it will hit an obstruction during its travel. These are the three red paths in the figure.
You are given a String water. An 'X' represents an obstruction, while a '.' represents water free from obstruction. You are to return an int representing the maximum distance a stone can travel and finally fall in the water, without hitting any obstructions, and without reaching the opposite bank (going beyond the end of the string). You may choose any initial distance for the throw, which starts from the left side of the string. A distance of 1 is the first character of the string, etc. If no initial throw will result in the stone landing in the water without hitting an obstruction, return 0.
Definition
Class: |
SkipStones |
Method: |
maxDistance |
Parameters: |
String |
Returns: |
int |
Method signature: |
int maxDistance(String water) |
(be sure your method is public) |
Notes
-
Obstructions are at water level, so the stone will not hit any obstructions while it's in the air.
Constraints
-
water will contain between 1 and 50 elements, inclusive.
-
Each element of water will contain between 1 and 50 characters, inclusive.
-
Each character of each element of water will be 'X' or '.'.
Examples
0)
| |
Returns: 11 | |
|
1)
| |
Returns: 3 | |
|
2)
| |
Returns: 22 | |
|
3)
| |
Returns: 15 | |
|
E序代码
//chapter03:Garbage.java
// Demonstration of the garbage
// collector and finalization
class Chair {
static boolean gcrun = false;
static boolean f = false;
static int created = 0;
static int finalized = 0;
int i;
Chair() {
i = ++created;
if(created == 47)
System.out.println("Created 47");
}
public void finalize() {
if(!gcrun) {
// The first time finalize() is called:
gcrun = true;
System.out.println(
"Beginning to finalize after " +
created + " Chairs have been created");
}
if(i == 47) {
System.out.println(
"Finalizing Chair #47, " +
"Setting flag to stop Chair creation");
f = true;
}
finalized++;
if(finalized >= created)
System.out.println(
"All " + finalized + " finalized");
}
}
public class Garbage {
public static void main(String[] args) {
// As long as the flag hasn't been set,
// make Chairs and Strings:
while(!Chair.f) {
new Chair();
new String("To take up space");
}
System.out.println(
"After all Chairs have been created:\n" +
"total created = " + Chair.created +
", total finalized = " + Chair.finalized);
// Optional arguments force garbage
// collection & finalization:
if(args.length > 0) {
if(args[0].equals("gc") &line;&line;
args[0].equals("all")) {
System.out.println("gc():");
System.gc();
}
if(args[0].equals("finalize") &line;&line;
args[0].equals("all")) {
System.out.println("runFinalization():");
System.runFinalization();
}
}
System.out.println("bye!");
}
} ///:~Z么执?SPAN lang=EN-US style="COLOR: red">java Garbage gc以后Q当所有对象创建完Q比?SPAN lang=EN-US>8000个)Q这时只清除?SPAN lang=EN-US>2000个(不定Q,应该只能创徏47个对象啊
分析Q?/FONT>
首先Q在一个@环当中创建对象,q且只是创徏Q而不引用Q也是说这个对象会自动的被pȝ当作垃圾处理掉。但h意,finalize()Ҏq不是立d会执行的Q执行的旉完全ql来军_。所以很有可能的情况是已l创Z20000个对象,才开始其中的某一个对象的清除工作Q这可能和时间或者系l内容的占用有关Q。看finalize()Ҏ中的一D代码:
if (!gcrun) {
gcrun = true;
System.out.println(
"\nBeginning to finalize after" + created + "Chairs have been created\nat ");
}
׃出现q样的结果:
Beginning to finalize after 25038 Chairs have been created
q时对象的创E仍在l(因ؓ已经Finalize的对象还不满47个,Chair.fq是falseQ。所?SPAN lang=EN-US>Chair.created会l增加?/FONT>
直到?SPAN lang=EN-US>47个对象被清除了,Chair.f被置?SPAN lang=EN-US>true了,创徏对象的@环才l束。看mainҎ中的一D代码:
System.out.println(
"\nAfter all chairs have been created:\n"
+ "total created ="
+ Chair.created
+ ",total finalized ="
+ Chair.finalized+"\n");
如上所_Chair.created是不断增加的Q而在q段代码执行之前Q又会有N个对象被释放掉了Q所?SPAN lang=EN-US>finalized也增加了?/FONT>
l果可能是这LQ?/FONT>
total created =29096,total finalized =73
其实q一q程和用的JVM有很大关p,执行l果可能会很不相同。但有一Ҏ可以肯定的,那就?SPAN style="COLOR: red">我们无法定JVM什么时候做对象的清除工?/SPAN>Q这也是Thinking in java中这D代码的惌说明的)Q?SPAN style="COLOR: red">可能会在q个对象刚刚?/SPAN>无用?/SPAN>的时候就清除掉了Q也可能滞后几秒Q甚xq不清除?/SPAN>
l论Q?/FONT>
不能指望finalize()Ҏ能稳定的工作Q尤其不能依靠它来做文g的关闭等操作Q由?SPAN lang=EN-US>finalize()的不定性,往往得不C惌的结果。事实上我们只需要知道所有无用的对象Q?SPAN lang=EN-US>JVM会自己清除就够了。省点心思去睡觉岂不是更好的一件事?Q)
z阳的天气可真是讨厌Q昨天好不容易放晴了一天,今天又下v了大雨,本来计划好去买衣服的Q现在只能汤了。这几天来上|查了很多的资料Qؓ了组Z个PHP、JSP、ASP的全能^収ͼPHP跟JSP的^台是l徏好了Q可是ASP怎么样都不行Q好不容易下了个IASP装上了,配置了之后却老是出现错误。哎NB怎么׃配个专业版的pȝl我呢,q样我就不用那么费劲了,只要把IIS跟Apache整合hp了。趁着有点旉把用apachel徏的PHP、JSPq_教程整理出来了,说实话光q两个都费了我好多的劲呀Q特别是JSPQ网上的教程都不知道是什么年代写的了Q几乎都不能用了Q我废了好几天的功夫才把q些零gl找齐,所以还特别C了下载的地址Q要下的p赶快了!好了Q废话不多说了,往下看吧。对了,另外再多说一句,下面的配|是我安装我本机的安装地址的,如果你的安装地址跟我的不W,那么你就要一些相应的改进Q还有,如果一下的下蝲地址无效了,你可以在我这留下你的邮箱Q我可以这些东西发l你?BR>
所需软g列表
1、apache_2.0.54-win32-x86-no_ssl.exe QApache web服务器) http://apache.justdn.org/......2.0.54-win32-x86-no_ssl.exe
2、php-5.0.5-Win32 QPHP语言解析器)
4、jdk1.4.2QJAVA 语言环境Q?
5、jakarta-tomcat-5.5.12 QTomcat JSP解析服务器) http://mirror.vmmatrix.ne......in/apache-tomcat-5.5.12.exe
7、mod_jk-1.2.14-apache-2.0.54.so.asc Q整合Apache+Tomcat的plusQ?http://apache.linuxforum.......1.2.14-apache-2.0.54.so.ascQؓ了找q个文g都把我给扄了,|上的教E到处都说要mod_jk_1.2.5_2.0.47.dllQ可是我找了两天死都找不刎ͼ后来到apache的官方网站看着生硬的ENL才找到这么个文gQ看文g名直觉就告诉我找对了Q现在的apache不都是用so扩展了么Q而且在那个页面也说明了这一点,要用还要改名,所以在q里特别指出下蝲地址Q让大家走很多的弯路)
开始安装:
一?Apahce+PHP安装配置
1、安装apache_2.0.54-win32-x86-no_ssl.exeQؓ了方便把路径改ؓc:\吧,其他都不用管一路next下去?
2、安装完成之后,apache服务自动加蝲Q这时打开览器,览Q?A href="http://localhost/">http://localhostQ出现apacheƢ迎面Q这步需要将C:\apache2\htdocs目录中的文g“index.html.en”改为“index.html”,方能昄Q;如果q步出现异常Q请查安装源文gQ重新安装?
3. 安装php-5.0.5-Win32,一般下载的PHP文gZ个免安装的压~包Q解压到CQ\PHP可以?nbsp;
4. 配置PHP和ApacheQ之能解析phpE序?nbsp;
PHP配置Q将C:\PHP\目录中的“php.ini-dist”改名“php.ini?然后d环境变量。在环境变量里的classpath中添加?;c:\php;”,在新Z个“PHPRC”的变量Q里面同hd?;c:\php;?nbsp;
Apache配置Q?nbsp;
打开C:\apache2\conf\httpd.conf
httpd.conf是apache的配|文Ӟ在此配置文g最后添加以下语句,用以支持phpE序Q?nbsp;
ScriptAlias /php/ "C:/PHP/"
AddType application/x-httpd-php .php3
AddType application/x-httpd-php .php
AddType application/x-httpd-php .phtml
Action application/x-httpd-php "/php/php.exe"
okQ接下来重启Apache服务器(如果加蝲PHP成功Q可以在Apache监控器中看到Apache/2.0.52(win32) PHP/5.0.4Q就可以试了PHP了,用编辑器~写如下语句Q?nbsp;
<?
phpinfo();
?>
保存文g名ؓ“test.php”到C:\apache2\htdocs目录Q然后打开览器,览Q?A href="http://localhost/test.php">http://localhost/test.phpQ出现PHP基本信息p明配|成功。严格按以上说明安装配置Q都会一ơ成功?
二、安装JDK和Tomcat
1. 安装j2sdk-1_4_2-windows-i586QJDK一定要在Tomcat之前安装Q默认安装\径就可以?BR>2. 安装Jakarta-Tomcat-5.5.12Q默认安装\径就可以?BR>4Q设|环境变量(桌面->我的电脑->右键点击->选择“属性?>高->环境变量Q,所有设|均在系l变量栏q行?BR>新徏->变量名:JAVA_HOME
->变量|C:\j2sdk1.4.2
新徏->变量名:TOMCAT_HOME
->变量|C:\Program Files\Apache Software Foundation\Tomcat 5.5
新徏->变量名: PATH
->变量|.;C:\j2sdk1.4.2\bin; Q前面的?;”一定要有)
修改增加环境变量 CLASSPATH (如果没有此变量名Q则新徏)
->增加变量|.;C:\j2sdk1.4.2\lib\dt.jar;C:\j2sdk1.4.2\lib\tool.jar;
C:\j2sdk1.4.2\lib\NetComponents.jar;
C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\classes;
C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib;
C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\lib\servlet-api.jar;Q前面的?;”一定要有)
5. 启动Tomcat服务器,打开览器,览Q?A href="http://localhost:8080/">http://localhost:8080/ Q出现TomcatƢ迎面Q如果这步出现异常,h查安装源文gQ重新安装?/P>
三、整合Apache+Tomcat服务?/P>
1. 复制mod_jk-1.2.14-apache-2.0.54.so.asc文g到C:\Apache2\modules目录Qƈ其文g名改为mod_jk.so?BR>2. Apache配置Q?BR>C:\apahce2\conf\httpd.conf
httpd.conf
在此配置文g最后添加以下语句,用以支持jspE序Q?BR>LoadModule jk_module modules/mod_jk.so
JkWorkersFile "C:/Program Files/Apache Software Foundation/Tomcat 5.5/conf/workers.properties"
JkMount /servlet/* ajp13
JkMount /*.jsp ajp13
q有要在
DirectoryIndex index.html index.html.var的后面加上default.jsp index.jspQ前面忘了说了,支持PHPq要加上index.php default.phpQ?/P>
3. 在C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\目录下,新徏文g名ؓ“workers.properties”的文gQ将如下内容复制到新建文件workers.properties中?/P>
workers.properties
# 只复制以下内容即可:
workers.tomcat_home=C:\Program Files\Apache Software Foundation\Tomcat 5.5
workers.java_home=C:\j2sdk1.4.2
ps=\
# worker.list=ajp13
worker.list=ajp12,ajp13
worker.ajp12.port=8007
worker.ajp12.host=localhost
worker.ajp12.type=ajp12
worker.ajp12.lbfactor=1
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.lbfactor=1
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=ajp12, ajp13
worker.inprocess.type=jni
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jaxp.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)parser.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)jasper.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)servlet.jar
worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)webserver.jar
worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar
worker.inprocess.cmd_line=-config
worker.inprocess.cmd_line=$(workers.tomcat_home)/conf/jni_server.xml
worker.inprocess.cmd_line=-home
worker.inprocess.cmd_line=$(workers.tomcat_home)
worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll
worker.inprocess.stdout=$(workers.tomcat_home)$(ps)inprocess.stdout
worker.inprocess.stderr=$(workers.tomcat_home)$(ps)inprocess.stderr
worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)
接下来重启Tomcat和Apache服务器(必须先重启Tomcat再重启ApacheQ不然会出错Q如果加载JK成功Q这个时候你可以在Apache监控器中看到Apache/2.0.52(win32) PHP/5.0.4 mod_jk/1.2.8Q就可以试了,把Tomcat的webappsq个目录拯到Apache的htdocs目录下面Q然后直接在览器地址栏输入:http://localhost/webapps ?http://localhost:8080如果昄的页面一样就说明成功了?/P>
剩下的就是连接MySQL了,但是本h不才一个叫mm.mysql-2.0.4-bin.jar的文件怎么也找不到Q只扑ֈ了个mysql-connector-java-3.1.5-gamma-bin.jar的文Ӟ可是我试q了一点用都没有,所以连接数据库的教E等我试验成功再说拉Q如果哪位高救救我的告诉我mm.mysql-2.0.4-bin.jar的下载地址或者告诉我IASP到底改如何配|,我真是感Ȁ不尽?BR>