java 管理对象是什么_Java工程师(16)对象的管理
包
包的創(chuàng)建規(guī)則
包可以有層次,在創(chuàng)建包時(shí)可以一次性創(chuàng)建多級(jí)包,上下級(jí)之間用“.”分割,如下圖所示。
訪問修飾符
簡介
訪問修飾符包括:private、protected、public。三者都可用于修飾成員變量、成員方法,從而影響成員變量、成員方法的訪問級(jí)別。
只有public可用于修飾類,從而影響類的訪問級(jí)別。
成員的訪問級(jí)別
成員變量、成員方法有4種訪問級(jí)別,它們與修飾符的關(guān)系見下表:
類的訪問級(jí)別
類有2種訪問級(jí)別,它們與修飾符的關(guān)系見下表:
垃圾回收
誰是垃圾
棧中數(shù)據(jù)會(huì)隨著方法調(diào)用的完成而出棧,不存在垃圾。堆中數(shù)據(jù)可以被棧引用,當(dāng)棧中數(shù)據(jù)出棧后,引用將消失,此時(shí)堆中的數(shù)據(jù)沒有銷毀,就是垃圾。
清理垃圾、回收內(nèi)存
所謂垃圾回收,是指清理堆中的垃圾數(shù)據(jù),從而回收內(nèi)存。Java的垃圾回收是自動(dòng)進(jìn)行的,即JVM會(huì)定時(shí)的掃描堆內(nèi)存,完成垃圾清理的任務(wù)。開發(fā)者也可以通過調(diào)用“System.gc()”來催促JVM盡快進(jìn)行垃圾回收,但不建議這樣做,因?yàn)檫@會(huì)打亂JVM的節(jié)奏,降低它的運(yùn)行效率。
擴(kuò)展閱讀:
GC(Garbage Collection)大部分人都把這項(xiàng)技術(shù)當(dāng)做Java語言的伴生成物。事實(shí)上,GC的歷史要遠(yuǎn)遠(yuǎn)比Java久遠(yuǎn),1960年誕生于MIT的Lisp是第一門真正石永紅內(nèi)存動(dòng)態(tài)分配和垃圾收集技術(shù)的語言。當(dāng)Lisp還在胚胎時(shí)期時(shí),人們就在思考GC需要完成的三件事情:哪些內(nèi)存需要回收?
什么時(shí)候回收?
如何回收?
經(jīng)過半個(gè)多世紀(jì)的發(fā)展,內(nèi)存的動(dòng)態(tài)分配與內(nèi)存回收技術(shù)已經(jīng)相當(dāng)成熟,一切看起來進(jìn)入了“自動(dòng)化”時(shí)代,那為什么我們還要去了解GC和內(nèi)存分配呢?
答案:當(dāng)需要排查各種內(nèi)存溢出、內(nèi)存泄露問題時(shí),當(dāng)垃圾收集器成為系統(tǒng)達(dá)到更高并發(fā)亮的瓶頸時(shí),我們就需要對(duì)這些“自動(dòng)化”的技術(shù)實(shí)施必要的監(jiān)控和調(diào)節(jié)。
垃圾收集器在對(duì)堆進(jìn)行回收前,第一件事就是要確定對(duì)象有哪些還“存活”著,哪些已經(jīng)“死去”(即不可能再被任何途徑使用的對(duì)象)?
引用計(jì)數(shù)器算法
很多人在面試時(shí)的回答就是引用計(jì)數(shù)器算法,那么什么是引用計(jì)數(shù)器算法呢?
給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器加1;當(dāng)應(yīng)用失效時(shí)計(jì)數(shù)器就減1;任何時(shí)刻計(jì)數(shù)器都為0的對(duì)象是不可能被使用的,就認(rèn)定它時(shí)死的對(duì)象。
該算法實(shí)現(xiàn)簡單,判定效率也很高,在大多數(shù)情況下它是一個(gè)不錯(cuò)的算法,比較著名的應(yīng)用案例,如:微軟的COM(Component Object Model)技術(shù)、Python語言、Squireel。但是Java語言中沒有選用該算法,其中最主要的原因就是它很難解決對(duì)象之間的相互循環(huán)應(yīng)用的問題。
舉例:
package com.jinxf;
public class ReferenceCountGC {
public Object instance = null;
private static final int _1MB = 1024*1024;
//這個(gè)成員屬性的唯一意義就是占點(diǎn)內(nèi)存,以便能在GC日志中看清楚是否被回收過 private byte[] bigSize = new byte[2*_1MB];
public static void main(String args[]){
ReferenceCountGC objA = new ReferenceCountGC();
ReferenceCountGC objB = new ReferenceCountGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
//假設(shè)在這行放生GC,那么objA和objB是否能被回收? System.gc();
}
}
main方法:對(duì)象objA和objB都有字段instance,通過該字段讓他們兩個(gè)互相引用,然后將他們兩個(gè)置為null不可能再被訪問,但是他們因?yàn)榛ハ嘁弥鴮?duì)象,導(dǎo)致它們的引用計(jì)數(shù)器都不為0,于是引用計(jì)數(shù)算法無法通知GC收集器收集它們。
com.jinxf.ReferenceCountGC
[GC (System.gc()) [PSYoungGen: 9359K->936K(153088K)] 9359K->944K(502784K), 0.0007702 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (System.gc()) [PSYoungGen: 936K->0K(153088K)] [ParOldGen: 8K->699K(349696K)] 944K->699K(502784K), [Metaspace: 3337K->3337K(1056768K)], 0.0038525 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 153088K, used 3947K [0x0000000715c00000, 0x0000000720680000, 0x00000007c0000000)
eden space 131584K, 3% used [0x0000000715c00000,0x0000000715fdafd8,0x000000071dc80000)
from space 21504K, 0% used [0x000000071dc80000,0x000000071dc80000,0x000000071f180000)
to space 21504K, 0% used [0x000000071f180000,0x000000071f180000,0x0000000720680000)
ParOldGen total 349696K, used 699K [0x00000005c1400000, 0x00000005d6980000, 0x0000000715c00000)
object space 349696K, 0% used [0x00000005c1400000,0x00000005c14aec08,0x00000005d6980000)
Metaspace used 3350K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 365K, capacity 388K, committed 512K, reserved 1048576K
Process finished with exit code 0
說明:
GC開頭的說明此次垃圾回收為Minor GC,而Full GC開頭的說明此次垃圾回收為stop-the-world的類型
PSYoungGen表示年輕代,ParOldGen表示老年代
方括號(hào)內(nèi)的"9359K->936K(153088K)]“表示"GC前該內(nèi)存區(qū)域已使用容量->GC后該內(nèi)存區(qū)域已使用容量(該內(nèi)存區(qū)域總?cè)萘?”
方括號(hào)外的"9359K->944K(502784K)“表示"GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆總?cè)萘?”
“0.0009304 secs"表示該內(nèi)存區(qū)域本次GC所占用的時(shí)間,單位是秒。有的收集器會(huì)給出更具體的時(shí)間數(shù)據(jù),如”[Time:user=0.01 sys=0.01 real=0.02 secs]",這里的user、sys、real與Linux的time命令所輸出的時(shí)間含義一致,分別代表用戶態(tài)消耗的CPU時(shí)間、內(nèi)核態(tài)消耗的CPU時(shí)間、操作從開始到結(jié)束所經(jīng)過的墻鐘時(shí)間。CPU時(shí)間和墻鐘時(shí)間的區(qū)別是,墻鐘時(shí)間包括各種非運(yùn)算的等待耗時(shí),如等待磁盤I/O、等待線程阻塞,而CPU時(shí)間不包括這些耗時(shí),但當(dāng)系統(tǒng)有多CPU或者多核的話,多線程操作會(huì)疊加這些CPU時(shí)間,所以若看到user或sys時(shí)間超過real時(shí)間也是完全正常的。
eden、from、to表示年輕代中各區(qū)域的劃分
Metaspace表示元空間的大小,這里用的是JDK1.8,如果是JDK1.7則沒有該區(qū)域
但是從GC日志中得出虛擬機(jī)并沒有因?yàn)檫@兩個(gè)對(duì)象相互引用就不回收他們,這也從側(cè)面上說明虛擬機(jī)并不是通過引用計(jì)數(shù)算法來判斷對(duì)象是否存活的。
根搜索算法
Java、C#、Lisp都是使用根搜索算法(GC Roots Tracing)判定對(duì)象是否存活的。該算法的思路是通過一系列的名為“GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑成為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒有任何引用鏈相連(用圖論的話來說就是從GC Roots到這個(gè)對(duì)象不可達(dá))時(shí),則證明此對(duì)象是不可用的。
如下圖所示,對(duì)象object5、object6、object7雖然互相有關(guān)聯(lián),但是他們到GC Roots是不可達(dá)的,所以它們將會(huì)被判定為是可回收的對(duì)象。
Java語言里,可作為GC Roots的對(duì)象包括下面幾種:虛擬機(jī)棧(棧幀中的本地變量表)中的引用對(duì)象
方法區(qū)中的類靜態(tài)屬性引用的對(duì)象。
方法區(qū)中常量引用的對(duì)象
本地方法棧中JNI(即一般說Native方法)的引用的對(duì)象
作業(yè)創(chuàng)建名為“com.jinxf.hello”的包,然后去workspace下找到這個(gè)項(xiàng)目,觀察src和bin下面的目錄結(jié)構(gòu)。
2.在Eclipse中導(dǎo)入老師上課所寫的“成員的訪問級(jí)別示例”項(xiàng)目。在Demo類的main方法中,調(diào)用“v.”,觀察彈出窗口中所能訪問到的Vehicle對(duì)象的內(nèi)容。
在Car類的test方法中,調(diào)用“super.”,觀察彈出窗口中所能訪問到的父類的內(nèi)容。
在Test類的main方法中,調(diào)用“v.”,觀察彈出窗口中所能訪問到的Vehicle對(duì)象的內(nèi)容。
總結(jié)
以上是生活随笔為你收集整理的java 管理对象是什么_Java工程师(16)对象的管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java udp 缓冲区_为什么特定的U
- 下一篇: java中多线程编程案例_Java中多线