??xml version="1.0" encoding="utf-8" standalone="yes"?> 来自 勤劳的蜜?/u>的博?/a>Q?
来自Phrancol的博?/a>Q?
来自八进制的博客Q?br />
]]>
来自BlueDavy的博?/a>Q?
一、判断题Q?0分)
1QJavaE序?创徏新的cd象用关键字newQ回收无用的cd象用关键字free?
2Q对象可以赋|只要使用赋值号Q等P卛_Q相当于生成了一个各属性与赋值对象相同的新对象?
3Q有的类定义时可以不定义构造函敎ͼ所以构造函C是必需的?
4Q类及其属性、方法可以同时有一个以上的修饰W来修饰?
5QJava的屏q坐标是以像素ؓ单位Q容器的左下角被定为坐标的L
6Q抽象方法必d抽象cMQ所以抽象类中的Ҏ都必L抽象Ҏ?
7QFinalcM的属性和Ҏ都必被final修饰W修饰?
8Q最l类不能z子类Q最l方法不能被覆盖?
9Q子c要调用父类的方法,必须使用super关键字?
10Q一个Javacd以有多个父类?
11Q如果p是父cParent的对象,而c是子cChild的对象,则语句c = p是正的?
12Q在java集合中,Vector和HashMap是线E安全的?
13Q当一个方法在q行q程中生一个异常,则这个方法会l止Q但是整个程序不一定终止运行?
14Q接口是Ҏ的类Q所以接口也可以l承Q子接口承父接口的所有常量和抽象Ҏ?
15Q用“+”可以实现字符串的拼接Q用- 可以从一个字W串中去除一个字W子丌Ӏ?
二、选择题(30分)
1、关于垃圾收集的哪些叙述是正的Q?nbsp; Q:
AQ程序开发者必自己创Z个线E进行内存释攄工作
BQ垃圾收集允许程序开发者明指定ƈ立即释放该内?
CQ垃圾收集将查ƈ释放不再使用的内?
DQ垃圾收集能够在期望的时间释放被java对象使用的内?
2、下面的哪些赋D句是不正的Q?nbsp; Q:
AQfloat f=11.1;
BQdouble d=5.3E12;
CQdouble d=3.14159;
DQdouble d=3.14DQ?
3、下面关于变量及其范围的陈述哪些是不正确的( Q:
AQ实例变量是cȝ成员变量
BQ实例变量用关键字static声明
CQ在Ҏ中定义的局部变量在该方法被执行时创?
DQ局部变量在使用前必被初始?
4、下列关于修饰符L的说法,错误的是Q?nbsp; Q:
AQabstract不能与finalq列修饰同一个类
BQabstractcM不可以有private的成?
CQabstractҎ必须在abstractcM
DQstaticҎ中能处理非static的属?
5、容器Panel和Applet~省使用的布局~辑{略是( Q:
A、BorderLayout B、FlowLayout C、GridLayout D、CardLayout
6、以下标识符中哪Ҏ不合法的( )Q?
A?BigMeaninglessName B?int
C? st D?1
7、mainҎ是Java ApplicationE序执行的入口点Q关于mainҎ的方法头以下哪项是合法的Q?nbsp; Q:
A?nbsp; public static void mainQ)
B?nbsp; public static void mainQString[ ] argsQ?
C?nbsp; public static int mainQString[ ] argQ?
D?nbsp; public void mainQString arg[ ]Q?
8、执行完以下代码int [ ] x = new int[25]Q后Q以下哪说明是正确的( Q:
A?nbsp; x[24]?
B?nbsp; x[24]未定?
C?nbsp; x[25]?
D?nbsp; x[0]为空
9、以下代码段执行后的输出l果为( Q:
int x=3Q?int y=10Q?
System.out.println(y%x);
A?
B?
C?
D?
10、以下哪个表辑ּ是不合法的( Q:
A、String x=”Hello”; int y=9; x+=y;
B、String x=”Hello”; int y=9; if(x= =y) { }
C、String x=”Hello”; int y=9; x=x+y;
D、String x=null; int y=(x!=null)&&(x.length()>0) ? x.length : 0
11、编译运行以下程序后Q关于输出结果的说明正确的是 Q?nbsp; Q:
public class Conditional{
public static void main(String args[ ]){
int x=4;
System.out.println(“value is “+ ((x>4) ? 99.9 :9));
}
}
A?nbsp; 输出l果为:value is 99.99
B?nbsp; 输出l果为:value is 9
C?nbsp; 输出l果为:value is 9.0
D?nbsp; ~译错误
12、以下声明合法的是( Q:
A?nbsp; default String sQ?
B?nbsp; public final static native int w( )
C?nbsp; abstract double dQ?
D?nbsp; abstract final double hyperbolicCosine( )
13、关于以下application的说明,正确的是Q?nbsp; Q:
1Q?nbsp; class StaticStuff
2Q?{
3Q?nbsp; static int x=10Q?
4Q?nbsp; static { x+=5Q}
5Q?nbsp; public static void mainQString args[ ]Q?
6Q?nbsp; {
7Q?nbsp; System.out.println(“x=” + x);
8Q?nbsp; }
9Q?nbsp; static { x/=3;}
10. }
A?4行与9行不能通过~译Q因为缺方法名和返回类?nbsp;
B?9行不能通过~译Q因为只能有一个静态初始化?
C?~译通过Q执行结果ؓQx=5
D、编译通过Q执行结果ؓQx=3
14、关于以下程序代码的说明正确的是Q?nbsp; Q:
1Qclass HasStatic{
2Q?nbsp; private static int x=100Q?
3Q?nbsp; public static void main(String args[ ]){
4Q?nbsp; HasStatic hs1=new HasStatic( );
5Q?nbsp; hs1.x++;
6Q?nbsp; HasStatic hs2=new HasStatic( );
7Q?nbsp; hs2.x++;
8Q?nbsp; hs1=new HasStatic( );
9Q?nbsp; hs1.x++;
10Q?nbsp; HasStatic.x- -;
11Q?nbsp; System.out.println(“x=”+x);
12Q?nbsp; }
13Q}
A?行不能通过~译Q因为引用了U有静态变?
B?0行不能通过~译Q因为x是私有静态变?
C、程序通过~译Q输出结果ؓQx=103
D、程序通过~译Q输出结果ؓQx=102
15、以下选项中@环结构合法的是( Q:
A、while (int i<7){
i++;
System.out.println(“i is “+i);
}
B、int j=3;
while(j){
System.out.println(“ j is “+j);
}
C、int j=0;
for(int k=0; j + k !=10; j++,k++){
System.out.println(“ j is “+ j + “k is”+ k);
}
D、int j=0;
do{
System.out.println( “j is “+j++);
if (j = = 3) {continue loop;}
}while (j<10);
三、简{题Q?0分)
1. 写出下列E序的运行结?
public class Cat
{
void mi( ) throws NullPointerException
{
System.out.println( “Cat mi mi .. “ );
}
}
public class SmallCat extends Cat
{int i=8;
void mi( ) throws Exception
{
System.out.println( “SmallCat mi mi .. “ );
}
public static void main( String[] a ) throws Exception
{
Cat cat = new SmallCat();
cat.mi();
}
}
写出下列E序的运行结?
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name = name;
}
public void play() {
ball = new Ball("Football");
System.out.println(ball.getName());
}
}
写出下列E序的运行结?
class Value{
public int i = 15;
}
public class Test{
public static void main(String argv[]){
Test t = new Test();
t.first();
}
public void first(){
int i = 5;
Value v = new Value();
v.i = 25;
second(v, i);
System.out.println(v.i);
}
public void second(Value v, int i){
i = 0;
v.i = 20;
Value val = new Value();
v = val;
System.out.println(v.i + " " + i);
}
}
写出下列E序的运行结?
class MyThread extends Thread{
public void run(){
System.out.println("MyThread: run()");
}
public void start(){
System.out.println("MyThread: start()");
}
}
class MyRunnable implements Runnable{
public void run(){
System.out.println("MyRunnable: run()");
}
public void start(){
System.out.println("MyRunnable: start()");
}
}
public class MyTest {
public static void main(String args[]){
MyThread myThread = new MyThread();
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
myThread.start();
thread.start();
}
}
]]>
二、基本概?/strong>
1、堆(Heap)
JVM理的内存叫堆。在32Bit操作pȝ上有1.5G-2G的限Ӟ?4Bit的就没有?
JVM初始分配的内存由-Xms指定Q默认是物理内存?/64但小?G?
JVM最大分配的内存?Xmx指定Q默认是物理内存?/4但小?G?
默认IZ堆内存小?0%ӞJVM׃增大堆直?Xmx的最大限Ӟ可以?XX:MinHeapFreeRatio=指定?
默认IZ堆内存大?0%ӞJVM会减堆直到-Xms的最限Ӟ可以?XX:MaxHeapFreeRatio=指定?
服务器一般设|?Xms?Xmx相等以避免在每次GC 后调整堆的大,所以上面的两个参数没啥用?nbsp;
2.基本攉法
可见Q没有免费的午餐Q无论采用复制还是标记清除算法,自动的东襉K要付出很大的性能代h?
3.分代
分代是Java垃圾攉的一大亮点,Ҏ对象的生命周期长短,把堆分ؓ3个代QYoungQOld和PermanentQ根据不同代的特炚w用不同的攉法Q扬镉K短也?
Young(Nursery)Q年M。研I表明大部分对象都是朝生暮死Q随生随灭的。因此所有收集器都ؓq轻代选择了复制算法?br /> 复制法优点是只讉Kz跃对象Q缺Ҏ复制成本高。因为年M只有量的对象能熬到垃圾攉Q因此只需量的复制成本。而且复制攉器只讉Kz跃对象Q对那些占了最大比率的d象视而不见,充分发挥了它遍历I间成本低的优点?
Young的默认gؓ4MQ随堆内存增大,Uؓ1/15QJVM会根据情况动态管理其大小变化?br /> -XX:NewRatio= 参数可以讄Young与Old的大比例,-server旉认ؓ1:2Q但实际上young启动时远低于q个比率Q如果信不过JVMQ也可以?Xmn性规定其大小Q有文推荐设ؓHeapd的1/4?
Young的大非帔R帔R要,?#8220;后面暂停旉优先攉?#8221;的论q?
Young里面又分?个区域,一个EdenQ所有新建对象都会存在于该区Q两个Survivor区,用来实施复制法。每ơ复制就是将Eden和第一块Survior的活对象复制到第2块,然后清空Eden与第一块Survior。Eden与Survivor的比例由-XX:SurvivorRatio=讄Q默认ؓ32。Survivio大了会浪费,了的话Q会使一些年d象潜逃到老h区,引v老h区的不安Q但q个参数Ҏ能q不重要?nbsp;
Old(Tenured)Q年老代。年M的对象如果能够挺q数ơ收集,׃q入老h区。老hZ用标记整理算法。因h区的对象都没那么ҎȝQ采用复制算法就要反复的复制对象Q很不合,只好采用标记清理法Q但标记清理法其实也不LQ每ơ都要遍历区域内所有对象,所以还是没有免费的午餐啊?
-XX:MaxTenuringThreshold=讄熬过q轻代多次攉后移入老h区,CMS中默认ؓ0Q熬q第一ơGCp{入,可以?XX:+PrintTenuringDistribution查看?
PermanentQ持久代?/strong>装蝲Class信息{基数据Q默?4MQ如果是cd多很多的服务E序Q需要加大其讄-XX:MaxPermSize=Q否则它满了之后会引起fullgc()或Out of Memory?注意SpringQHibernateq类喜欢AOP动态生成类的框枉要更多的持久代内存?
4.minor/major collection
每个代满了之后都会促发collectionQ(另外Concurrent Low Pause Collector默认在老h?8%的时候促?。GC用较高的频率对youngq行扫描和回Ӟq种叫做minor collection?br /> 而因为成本关pdOld的检查回攉率要低很多,同时对Young和Old的收集称为major collection?br /> System.gc()会引发major collectionQ?XX:+DisableExplicitGC止它,或设为CMSq发-XX:+ExplicitGCInvokesConcurrent?
5.结
Young -- minor collection -- 复制法
Old(Tenured) -- major colletion -- 标记清除/标记整理法
三、收集器
1.古老的串行攉?Serial Collector)
使用 -XX:+UseSerialGCQ策略ؓq轻代串行复Ӟq老代串行标记整理?
2.吞吐量优先的q行攉?Throughput Collector)
使用 -XX:+UseParallelGC Q也是JDK5 -server的默认倹{策略ؓQ?br /> 1.q轻代暂停应用程序,多个垃圾攉U程q行的复制收集,U程数默认ؓCPU个数QCPU很多Ӟ可用–XX:ParallelGCThreads=减少U程数?br /> 2.q老代暂停应用E序Q与串行攉器一P单垃圾收集线E标记整理?
所以需?+的CPU时才会优于串行收集器Q适用于后台处理,U学计算?
可以使用-XX:MaxGCPauseMillis= ?-XX:GCTimeRatio 来调整GC的时间?
3.暂停旉优先的ƈ发收集器(Concurrent Low Pause Collector-CMS)
前面说了q么多,都是Zq节做铺?.....
使用-XX:+UseConcMarkSweepGCQ策略ؓQ?br /> 1.q轻代同h暂停应用E序Q多个垃圾收集线Eƈ行的复制攉?br /> 2.q老代则只有两ơ短暂停Q其他时间应用程序与攉U程q发的清除?
3.1 q老代详述
q行(Parallel)与ƈ?Concurrent)仅一字之差,q行指多条垃圾收集线Eƈ行,q发指用LE与垃圾攉U程q发Q程序在l箋q行Q而垃圾收集程序运行于另一个个CPU上?
q发攉一开始会很短暂的停止一ơ所有线E来开始初始标记根对象Q然后标记线E与应用U程一起ƈ发运行,最后又很短的暂停一ơ,多线E?strong>q行的重新标C前可能因为ƈ发而漏掉的对象Q然后就开始与应用E序q发的清除过E。可见,最长的两个遍历q程都是与应用程序ƈ发执行的Q比以前的串行算法改q太多太多了Q!Q?
串行标记清除是等q老代满了再开始收集的Q而ƈ发收集因与应用程序一赯行,如果满了才收集,应用E序无内存可用Q所以系l默?8%满的时候就开始收集。内存已讑־较大Q吃内存又没有这么快的时候,可以?XX:CMSInitiatingOccupancyFraction=恰当增大该比率?
3.2 q轻代详q?/strong>
可惜对年M的复制收集,依然必须停止所有应用程序线E,原理如此Q只能靠多CPUQ多攉U程q发来提高收集速度Q但除非你的Server独占整台服务器,否则如果服务器上本nq有很多其他U程Ӟ切换h速度?.... 所以,搞到最后,暂停旉的瓶颈就落在了年M的复制算法上?
因此Young的大设|挺重要的,大点׃用频JGCQ而且增大GC的间隔后Q可以让多点对象自己L而不用复制了。但Young增大ӞGC造成的停时间攀升得非常恐怖,比如在我的机器上Q默?M的YoungQ只需要几毫秒的时_64M升?0毫秒Q而升?56MӞp?00毫秒了,峰D会攀到恐怖的800ms。谁叫复制算法,要等Young满了才开始收集,开始收集就要停止所有线E呢?
3.3 持久?/strong>
可设|?XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabledQCMS攉持久代的c,而不是fullgcQnetbeans5.5 performance文的推荐?/code>
4.增量(train法)攉?Incremental Collector)
已停止维护,–Xincgc选项默认转ؓq发攉器?
四、暂停时间显C?/strong>
加入下列参数 (请将PrintGC和Details中间的空格去掉,CSDN很怪的认ؓ是禁止字句)
-verbose:gc -XX:+PrintGC Details -XX:+PrintGCTimeStamps
会程序运行过E中显C如下输?
9.211: [GC 9.211: [ParNew: 7994K->0K(8128K), 0.0123935 secs] 427172K->419977K(524224K), 0.0125728 secs]
昄在程序运行的9.211U发生了Minor的垃圾收集,前一D|据针Ҏ生区Q从7994k整理?kQ新生区dؓ8128kQ程序暂停了12msQ而后一D|据针Ҏ个堆?
对于q老代的收集,暂停发生在下面两个阶D,CMS-remark的中断是17毫秒Q?
[GC [1 CMS-initial-mark: 80168K(196608K)] 81144K(261184K), 0.0059036 secs]
[1 CMS-remark: 80168K(196608K)] 82493K(261184K),0.0168943 secs]
再加两个参数 -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTimeҎ停时间看得更清晰?
五、真正不停的BEA JRockit 与Sun RTS2.0
Bea?a >JRockit 5.0 R27 的特色之一是动态决定的垃圾攉{略Q用户可以决定自己关心的是吞吐量Q暂停时间还是确定的暂停旉Q再由JVM在运行时动态决定、改变改变垃圾收集策略?br />
它的Deterministic GC的选项?Xgcprio: deterministicQ号U可以把暂停可以控制?0-30毫秒Q非常的牛,一句Deterministic道尽了RealTime的真谛?不过l看一下文,30ms的测试环境是1 GB heap ?q_ 30% 的活跃对?也就?00M)zd对象Q? ?Xeon 3.6 GHz 4G内存 Q或者是4 个Xeon 2.0 GHzQ?G内存?
最可惜JRockt的license很奇怪,虽然qx使用免费Q但q个30ms的选项需要购买整个Weblogic Real Time Server的license?nbsp;
其他免费选项Q有Q?/p>
JavaOne2007上有Sun?Java Real-Time System 2.0 的介l,RTS2.0ZJDK1.5Q在Real-Time Garbage Collctor上又有改q,但还在beta版状态,只供lOEMQ更怪?
六、JDK 6.0的改q?/strong>
因ؓJDK5.0在Young较大时的表现q是不够让h满意Q又l箋看JDK6.0的改q,l果E稍失望Q不涉及我最头痛的年M复制攉改良?
1.q老代的标?清除攉Qƈ行执行标?/strong>
JDK5.0只开了一条收集进E与应用U程q发标识Q?.0可以开多条攉U程来做标识Q羃短标识老h区所有活动对象的旉?
2.加大了Young区的默认大小
默认大小?M加到16MQ从堆内存的1/15增加?/7
3.System.gc()可以与应用程序ƈ发执?/strong>
使用-XX:+ExplicitGCInvokesConcurrent 讄
七、小l?/strong>
1. JDK5.0/6.0
对于服务器应用,我们使用Concurrent Low Pause CollectorQ对q轻代,暂停时多U程q行复制攉Q对q老代Q收集器与应用程序ƈ行标?-整理攉Q以辑ֈ量短的垃圾攉旉?
本着没有深刻试前不要胡׃化的宗旨Q命令行属性只需单写为:
然后要根据应用的情况Q在试软g辅助可以下看看有没有JVM的默认值和自动理做的不够的地方可以调_?xmn 设Young的大,-XX:MaxPermSize设持久代大小{?
2. JRockit 6.0 R27.2
但因为JDK5的测试结果实在不能满意,后来又尝试了JRockitQM效果要好些?br /> JRockit的特Ҏ动态垃圾收集器是根据用户关心的特征动态决定收集算法的Q参数如?/p>
1.垃圾攉法的核心思想
Java语言建立了垃圾收集机Ӟ用以跟踪正在使用的对象和发现q回收不再?引用)的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽Q以及不恰当的内存释放所造成的内存非法引用?/font>
垃圾攉法的核心思想是:对虚拟机可用内存I间Q即堆空间中的对象进行识别,如果对象正在被引用,那么U其为存zd象,反之Q如果对象不再被引用Q则为垃圑֯象,可以回收其占据的I间Q用于再分配。垃圾收集算法的选择和垃圾收集系l参数的合理调节直接影响着pȝ性能Q因此需要开发h员做比较深入的了解?/font>
2.触发主GC(Garbage Collector)的条?/strong>
JVMq行ơGC的频率很?但因UGC占用旉极短,所以对pȝ产生的媄响不大。更值得x的是主GC的触发条?因ؓ它对pȝ影响很明显。ȝ来说,有两个条件会触发主GC:
①当应用E序I闲?x有应用线E在q行?GC会被调用。因为GC在优先最低的U程中进?所以当应用忙时,GCU程׃会被调用,但以下条仉外?/font>
②Java堆内存不x,GC会被调用。当应用U程在运?q在q行q程中创建新对象,若这时内存空间不?JVM׃强制地调用GCU程,以便回收内存用于新的分配。若GC一ơ之后仍不能满内存分配的要?JVM会再q行两次GC作进一步的试,若仍无法满要求,?JVM报“out of memory”的错?Java应用停止?/font>
׃是否q行主GC由JVMҎpȝ环境军_,而系l环境在不断的变化当?所以主GC的运行具有不定?无法预计它何时必然出?但可以确定的是对一个长期运行的应用来说,其主GC是反复进行的?/font>
3.减少GC开销的措?/strong>
Ҏ上述GC的机?E序的运行会直接影响pȝ环境的变?从而媄响GC的触发。若不针对GC的特点进行设计和~码,׃出现内存ȝ{一pd负面影响。ؓ了避免这些媄?基本的原则就是尽可能地减垃圑֒减少GCq程中的开销。具体措施包括以下几个方?
(1)不要昑ּ调用System.gc()
此函数徏议JVMq行主GC,虽然只是而非一?但很多情况下它会触发主GC,从而增加主GC的频?也即增加了间歇性停的ơ数?/font>
(2)量减少临时对象的?/font>
临时对象在蟩出函数调用后,会成为垃?用临时变量q当于减少了垃圄产生,从而g长了出现上述W二个触发条件出现的旉,减少了主GC的机会?/font>
(3)对象不用时最好显式置为Null
一般而言,为Null的对象都会被作ؓ垃圾处理,所以将不用的对象显式地设ؓNull,有利于GC攉器判定垃?从而提高了GC的效率?/font>
(4)量使用StringBuffer,而不用String来篏加字W串(详见blog另一文章JAVA中String与StringBuffer)
׃String是固定长的字W串对象,累加String对象?q在一个String对象中扩?而是重新创徏新的String对象,如Str5=Str1+Str2+Str3+Str4,q条语句执行q程中会产生多个垃圾对象,因ؓҎ?#8220;+”操作旉必须创徏新的String对象,但这些过渡对象对pȝ来说是没有实际意义的,只会增加更多的垃圾。避免这U情况可以改用StringBuffer来篏加字W串,因StringBuffer是可变长?它在原有基础上进行扩?不会产生中间对象?/font>
(5)能用基本cd如Int,Long,׃用Integer,Long对象
基本cd变量占用的内存资源比相应对象占用的少得多,如果没有必要,最好用基本变量?/font>
(6)量用静态对象变?/font>
静态变量属于全局变量,不会被GC回收,它们会一直占用内存?/font>
(7)分散对象创徏或删除的旉
集中在短旉内大量创建新对象,特别是大对象,会导致突焉要大量内?JVM在面临这U情冉|,只能q行主GC,以回收内存或整合内存片,从而增加主GC的频率。集中删除对?道理也是一L。它使得H然出现了大量的垃圾对象,I闲I间必然减少,从而大大增加了下一ơ创建新对象时强制主GC的机会?/font>
4.gc与finalizeҎ
⑴gcҎh垃圾回收
使用System.gc()可以不管JVM使用的是哪一U垃圑֛收的法Q都可以hJava的垃圑֛收。需要注意的是,调用System.gc()也仅仅是一个请求。JVM接受q个消息后,q不是立卛_垃圾回收Q而只是对几个垃圾回收法做了加权Q垃圾回收操作Ҏ发生Q或提早发生Q或回收较多而已?/font>
⑵finalizeҎ透视垃圾攉器的q行
在JVM垃圾攉器收集一个对象之?Q一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下QJava提供了缺省机制来l止化该对象释放资源Q这个方法就是finalize()。它的原型ؓQ?/font>
protected void finalize() throws Throwable
在finalize()Ҏq回之后Q对象消失,垃圾攉开始执行。原型中的throws Throwable表示它可以抛ZQ何类型的异常?/font>
因此Q当对象卛_被销毁时Q有旉要做一些善后工作。可以把q些操作写在finalize()Ҏ里?/font>
⑶代码示?br />
5.Java 内存泄漏
׃采用了垃圑֛收机ӞM不可辑֯?对象不再被引?都可以由垃圾攉U程回收。因此通常说的Java 内存泄漏其实是指无意识的、非故意的对象引用,或者无意识的对象保持。无意识的对象引用是指代码的开发h员本来已l对对象使用完毕Q却因ؓ~码的错误而意外地保存了对该对象的引用(q个引用的存在ƈ不是~码人员的主观意?Q从而得该对象一直无法被垃圾回收器回收掉Q这U本来以为可以释放掉的却最l未能被释放的空间可以认为是?#8220;泄漏?#8221;?/font>
考虑下面的程?在ObjStackcM,使用push和popҎ来管理堆栈中的对象。两个方法中的烦?index)用于指示堆栈中下一个可用位|。pushҎ存储Ҏ对象的引用ƈ增加索引?而popҎ减小索引值ƈq回堆栈最上面的元素。在mainҎ?创徏了容量ؓ64的栈,q?4ơ调用pushҎ向它d对象,此时index的gؓ64,随后?2ơ调用popҎ,则index的值变?2,出栈意味着在堆栈中的空间应该被攉。但事实?popҎ只是减小了烦引?堆栈仍然保持着寚w些对象的引用。故32个无用对象不会被GC回收,造成了内存渗漏?/font>
6.如何消除内存泄漏
虽然Java虚拟?JVM)及其垃圾攉?garbage collectorQGC)负责理大多数的内存dQJava软gE序中还是有可能出现内存泄漏。实际上Q这在大型项目中是一个常见的问题。避免内存泄漏的W一步是要弄清楚它是如何发生的。本文介l了~写Java代码的一些常见的内存泄漏陷阱Q以及编写不泄漏代码的一些最佛_c一旦发生了内存泄漏Q要指出造成泄漏的代码是非常困难的。因此本文还介绍了一U新工具Q用来诊断泄漏ƈ指出Ҏ原因。该工具的开销非常,因此可以使用它来L处于生中的pȝ的内存泄漏?/font>
垃圾攉器的作用
虽然垃圾攉器处理了大多数内存管理问题,从而ɾ~程人员的生zd得更L了,但是~程人员q是可能犯错而导致出现内存问题。简单地_GC循环地跟t所有来?#8220;?#8221;对象(堆栈对象、静态对象、JNI句柄指向的对象,诸如此类)的引用,q将所有它所能到辄对象标记为活动的。程序只可以操纵q些对象;其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象,q么做就是安全的?/font>
虽然内存理可以说是自动化的Q但是这q不能ɾ~程人员免受思考内存管理问题之苦。例如,分配(以及释放)内存M有开销Q虽然这U开销对编Eh员来说是不可见的。创Z太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一?在其他条件相同的情况??/font>
而且Q与本文更ؓ密切相关的是Q如果忘?#8220;释放”先前分配的内存,可能造成内存泄漏。如果程序保留对永远不再使用的对象的引用Q这些对象将会占用ƈ耗尽内存Q这是因动化的垃圾收集器无法证明q些对象不再用。正如我们先前所说的Q如果存在一个对对象的引用,对象p定义为活动的Q因此不能删除。ؓ了确保能回收对象占用的内存,~程人员必须保该对象不能到达。这通常是通过对象字D设|ؓnull或者从集合(collection)中移除对象而完成的。但是,注意Q当局部变量不再用时Q没有必要将其显式地讄为null。对q些变量的引用将随着Ҏ的退自动清除?/font>
概括地说Q这是内存托管语言中的内存泄漏产生的主要原因:保留下来却永q不再用的对象引用?/font>
典型泄漏
既然我们知道了在Java中确实有可能发生内存泄漏Q就让我们来看一些典型的内存泄漏及其原因?/font>
全局集合
在大的应用程序中有某U全局的数据储存库是很常见的,例如一个JNDI树或一个会话表。在q些情况下,必须注意理储存库的大小。必L某种机制从储存库中移除不再需要的数据?/font>
q可能有多种ҎQ但是最常见的一U是周期性运行的某种清除d。该d验证储存库中的数据QƈU除M不再需要的数据?/font>
另一U管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零Ӟ该元素就可以从集合中U除了?/font>
~存
~存是一U数据结构,用于快速查扑ַl执行的操作的结果。因此,如果一个操作执行v来很慢,对于常用的输入数据,可以将操作的结果缓存,q在下次调用该操作时使用~存的数据?/font>
~存通常都是以动态方式实现的Q其中新的结果是在执行时d到缓存中的。典型的法是:
查结果是否在~存中,如果在,p回结果?/font>
如果l果不在~存中,p行计?/font>
计出来的l果d到缓存中Q以便以后对该操作的调用可以使用?/font>
该算法的问题(或者说是潜在的内存泄漏)出在最后一步。如果调用该操作时有相当多的不同输入Q就有相当多的l果存储在缓存中。很明显q不是正的Ҏ?/font>
Z预防q种h潜在破坏性的设计Q程序必ȝ保对于缓存所使用的内存容量有一个上限。因此,更好的算法是Q?/font>
查结果是否在~存中,如果在,p回结果?/font>
如果l果不在~存中,p行计?/font>
如果~存所占的I间q大Q就U除~存最久的l果?/font>
计出来的l果d到缓存中Q以便以后对该操作的调用可以使用?/font>
通过始终U除~存最久的l果Q我们实际上q行了这L假设Q在来Q比L存最久的数据Q最q输入的数据更有可能用到。这通常是一个不错的假设?/font>
新算法将保~存的容量处于预定义的内存范围之内。确切的范围可能很难计算Q因为缓存中的对象在不断变化Q而且它们的引用包|万象。ؓ~存讄正确的大是一w常复杂的dQ需要将所使用的内存容量与索数据的速度加以q?/font>
解决q个问题的另一U方法是使用java.lang.ref.SoftReferencec跟t缓存中的对象。这U方法保证这些引用能够被U除Q如果虚拟机的内存用而需要更多堆的话?/font>
ClassLoader
Java ClassLoaderl构的用ؓ内存泄漏提供了许多可乘之机。正是该l构本n的复杂性ClassLoader在内存泄漏方面存在如此多的问题。ClassLoader的特别之处在于它不仅涉及“常规”的对象引用,q涉及元对象引用Q比如:字段、方法和cR这意味着只要有对字段、方法、类或ClassLoader的对象的引用QClassLoader׃ȝ在JVM中。因为ClassLoader本n可以兌许多cd光态字D,所以就有许多内存被泄漏了?/font>
定泄漏的位|?/font>
通常发生内存泄漏的第一个迹象是Q在应用E序中出COutOfMemoryError。这通常发生在您最不愿意它发生的生产环境中Q此时几乎不能进行调试。有可能是因为测试环境运行应用程序的方式与生产系l不完全相同Q因而导致泄漏只出现在生产中。在q种情况下,需要用一些开销较低的工h监控和查扑ֆ存泄漏。还需要能够无需重启pȝ或修改代码就可以这些工兯接到正在q行的系l上。可能最重要的是Q当q行分析Ӟ需要能够断开工具而保持系l不受干扰?/font>
虽然OutOfMemoryError通常都是内存泄漏的信P但是也有可能应用E序实正在使用q么多的内存;对于后者,或者必d加JVM可用的堆的数量,或者对应用E序q行某种更改Q它用较的内存。但是,在许多情况下QOutOfMemoryError都是内存泄漏的信受一U查明方法是不间断地监控GC的活动,定内存使用量是否随着旉增加。如果确实如此,可能发生了内存泄漏?/font>
sudo apt-get install mysql-server
q个应该很简单了Q而且我觉得大家在安装斚w也没什么太大问题,所以也׃多说了,下面我们来讲讲配|?
配置MySQL
注意Q在Ubuntu下MySQL~省是只允许本地讉K的,如果你要其他机器也能够访问的话,那么需要改?etc/mysql/my.cnf配置文g了!下面我们一步步地来Q?
默认的MySQL安装之后根用h没有密码的,所以首先用根用戯入:
$mysql -u root
在这里之所以用-u root是因为我现在是一般用PfirehareQ,如果不加-u root的话Qmysql会以为是firehare在登录。注意,我在q里没有q入根用h式,因ؓ没必要。一般来_对mysql中的数据库进行操作, Ҏ没必要进入根用户模式Q只有在讄时才有这U可能?
q入mysql之后Q最要紧的就是要讄Mysql中的root用户密码了,否则QMysql服务无安全可a了?
mysql> GRANT ALL PRIVILEGES ON *.* TO root@localhost IDENTIFIED BY "123456";
注意Q我q儿用的?23456做ؓroot用户的密码,但是该密码是不安全的Q请大家最好用大写字母与数字合的密码Q且不少?位?
q样的话Q就讄好了MySQL中的root用户密码了,然后qroot用户建立你所需要的数据库。我q里׃xoopsZQ?
mysql>CREATE DATABASE xoopsQ?
mysql>GRANT ALL PRIVILEGES ON xoops.* TO xoops_root@localhost IDENTIFIED BY "654321";
q样徏立了一个xoops_roots的用P它对数据库xoops有着全部权限。以后就用xoops_root来对xoops数据库进行管理,而无需要再用root用户了,而该用户的权限也只被限定在xoops数据库中?
如果你想q行q程讉K或控Ӟ那么你要做两件事Q?
其一Q?
mysql>GRANT ALL PRIVILEGES ON xoops.* TO xoops_root@"%" IDENTIFIED BY "654321";
允许xoops_root用户可以从Q意机器上dMySQL?
其二Q?
$sudo gedit /etc/mysql/my.cnf
老的版本?
>skip-networking => # skip-networking
新的版本?
>bind-address=127.0.0.1 => bind-address= 你机器的IP
q样可以允许其他机器访问MySQL了?