基礎(chǔ)了解
Java 程序的執(zhí)行過(guò)程:Java 源代碼文件(.Java文件)-> Java Compiler(Java編譯器)->Java 字節(jié)碼文件(.class文件)->類加載器(Class Loader)->Runtime Data Area(運(yùn)行時(shí)數(shù)據(jù))-> Execution Engine(執(zhí)行引擎)
各種基本類型:boolean、byte、char、short、int、float、long、double;
對(duì)象引用:reference類型 不等于對(duì)象本身,可能是對(duì)象的句柄也可能對(duì)象的引用指針
局部變量默認(rèn)沒有初始值,不賦值是不可以使用的。和類變量(默認(rèn)是有的)不一樣;
額外了解:插入式注解處理器:需要繼承AbstractProcessor;
內(nèi)存管理機(jī)制
本地方法棧和虛擬機(jī)棧有的虛擬機(jī)是不分的;
jvm各個(gè)區(qū)域的概要
對(duì)象訪問定位
句柄優(yōu)勢(shì):reference本身不需要修改,只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針
直接指針訪問優(yōu)勢(shì):最大好處速度快。節(jié)省了一次指針定位的開銷;
HotSpot采用此方式
對(duì)象的布局
3個(gè)區(qū)域:對(duì)象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)和對(duì)齊填充(Padding)
header:(官方稱 Mark Word)運(yùn)行時(shí)數(shù)據(jù),入哈希碼(HashCode)、GC分代年齡 鎖狀態(tài)標(biāo)識(shí)
Instance Data:類型指針,既對(duì)象只想他的類元數(shù)據(jù)的指針;
Padding:因?yàn)閷?duì)象的大小必須是8字節(jié)的整數(shù)倍。如果數(shù)據(jù)沒有對(duì)齊。需要Padding來(lái)補(bǔ)全
垃圾收集器與內(nèi)存分配策略
主要思考的問題:
標(biāo)記-那些內(nèi)存(那些死,那些活著)需要回收?
什么時(shí)候回收?
如何回收?
標(biāo)記概要
標(biāo)記算法
1)引用計(jì)數(shù)法(不能用):每當(dāng)一個(gè)地方引用它時(shí),計(jì)數(shù)器+1,引用失效時(shí),計(jì)數(shù)器-1,任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能在被使用
java沒有用 最主要的原因很難解決對(duì)象之間互相循環(huán)引用的問題;
**> public class ReferenceCountingGC {
public Object instance=null; public static void main(String[] args) { ReferenceCountingGC objA= new ReferenceCountingGC(); ReferenceCountingGC objB= new ReferenceCountingGC(); objA.instance=objB; objB.instance=objA; objA=null; objB=null; }
}**
2)可達(dá)性分析算法:
Java 語(yǔ)言中,可作為GC Roots的對(duì)象包括下面幾種;
虛擬機(jī)棧中(棧幀中的本地變量表)的引用對(duì)象
方法區(qū)中類靜態(tài)屬性引用對(duì)象
方法區(qū)中類常量引用對(duì)象
本地方法棧JNI引用的對(duì)象
四種引用
引用分為四種 強(qiáng),軟,弱,虛四種 強(qiáng)度依次減弱
強(qiáng)引用:類似Object obj=new Object() 這類引用,只要強(qiáng)引用還在,垃圾收集器就永遠(yuǎn)不會(huì)回收被引用的對(duì)象;
軟引用:用來(lái)描述一些還有用但并未必須的對(duì)象。內(nèi)存溢出異常之前,會(huì)把這些對(duì)象列入回收范圍之內(nèi)進(jìn)行二次回收。如果回收后還沒有足夠的內(nèi)存這回OOM;
弱引用:用來(lái)描述非必須的對(duì)象。若引用關(guān)聯(lián)的對(duì)象只能活到下一次垃圾回收之前;
虛引用:唯一目的對(duì)象被回收時(shí)收到一個(gè)系統(tǒng)通知
不可達(dá)對(duì)象的最后歷程
總結(jié):finalize()方法不執(zhí)行或者只能執(zhí)行一次
不可達(dá)對(duì)象,也并非”非死不可” 這時(shí)候是在緩刑階段。要真正宣告死亡,至少要經(jīng)理兩次標(biāo)記過(guò)程。
如果對(duì)象進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒有GC Roots相關(guān)聯(lián)的引用鏈,會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選條件是此對(duì)象是否有必要執(zhí)行finalize()方法。
對(duì)象沒有覆蓋finalize方法(逃脫命運(yùn)的最后機(jī)會(huì)),或者finalize()方法被虛擬機(jī)掉用過(guò)(只能執(zhí)行一次),虛擬機(jī)將這兩種情況都視為”沒有必要執(zhí)行”
如果被判定有必要執(zhí)行,那么對(duì)象會(huì)放置叫一個(gè)F-Queue的隊(duì)列之中,并且稍后虛擬機(jī)自動(dòng)建立Finalize線程去執(zhí)行它既f(wàn)inalize方法
但并不承諾會(huì)等待他運(yùn)行結(jié)束,怕死循環(huán)或者運(yùn)行緩慢。finalize方法是逃脫命運(yùn)的最后機(jī)會(huì),如果沒有逃脫就真的被回收了;
垃圾收集算法
標(biāo)記-清除算法(基礎(chǔ)算法,剩下的都是基于它的不足而進(jìn)行改進(jìn)的)
標(biāo)記:標(biāo)記所有需要回收的對(duì)象
清除:統(tǒng)一回收所有被標(biāo)記的對(duì)象
不足1:效率問題,標(biāo)記和清除效率都不高;
不足2:空間問題,產(chǎn)生大量的不連續(xù)的內(nèi)存碎片
復(fù)制(Copying)算法
內(nèi)存容量劃分兩個(gè)大小相等的兩塊,每次使用其中的一塊。這塊用完了復(fù)制存活的對(duì)象到另一塊,在把這塊清理掉
不足:代價(jià)太高 把內(nèi)存縮小為原來(lái)的一半;
現(xiàn)代的商用虛擬街都采用這種算法來(lái)回收新生代;因?yàn)樾律际?朝生暮死 所以不需要1:1來(lái)劃分
而將內(nèi)存分為一塊較大的Eden 和兩個(gè)較小的Survivor 默認(rèn)大小比;8:1, 每次新生代中可用的內(nèi)存空間是整個(gè)新生代容量的90=(Eden+Survivor),
“浪費(fèi)” 10 因?yàn)闆]辦法保證回收只有不多于10的存活,Survivor空間不夠需要老年代進(jìn)行 擔(dān)保;
0
標(biāo)記-整理(Mark-Compact)算法(老年代常用)
標(biāo)記和以前一樣,后續(xù)步驟不是直接回收,而是存活對(duì)象向一端移動(dòng),然后清理邊界以外的內(nèi)存;
分代收集算法
根據(jù)對(duì)象存活周期將內(nèi)存劃分不同的幾塊。一般堆分為 新生代 和老年代。這樣根據(jù)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴?/P>
新生代:少量存活 選擇復(fù)制算法
老年代:存活率高,沒有額外空間擔(dān)保,必須使用 標(biāo)記清理 或者標(biāo)記整理;
GC會(huì)產(chǎn)生停頓(Sun也叫它 “Stop The World”),OoMap 存放著GC Roots,不是每條指令都生成一個(gè)。
不是任何時(shí)都能停下來(lái)進(jìn)行 GC ,只有在 “特定的位置” 才可以GC 這個(gè)位置也叫安全點(diǎn)(Safepoint)
安全點(diǎn)的選定基本上是以程序”是否具有讓程序長(zhǎng)時(shí)間執(zhí)行的特征”為標(biāo)準(zhǔn)選定的
關(guān)于安全點(diǎn)另一個(gè)需要考慮的就是如何在GC發(fā)生的時(shí)讓所有線程都”跑”到最近的安全點(diǎn)上在停下來(lái);有兩種方案
搶先式中斷(Preemptive Suspension)(現(xiàn)在幾乎都這種方案):不需要線程的執(zhí)行代碼主動(dòng)配合,GC發(fā)生時(shí)候先把線程全部中斷,如果有線程不在安全點(diǎn),就回復(fù)線程讓它跑到安全點(diǎn)。
主動(dòng)式中斷(Voluntary Suspension):當(dāng)GC需要中斷線程的時(shí)候,不對(duì)線程造作,僅僅簡(jiǎn)單地設(shè)置一個(gè)標(biāo)志位,各個(gè)線程執(zhí)行的時(shí)候主動(dòng)去輪詢這個(gè)標(biāo)志位,發(fā)現(xiàn)中斷標(biāo)志位真就掛起,輪詢標(biāo)志的地方安全點(diǎn)重合。
而對(duì)于不執(zhí)行的線程,任何時(shí)間都是安全的也稱為安全區(qū);
垃圾收集器
7種垃圾收集器的介紹
G1收集器因?yàn)闆]有商用的就不寫了;
Serial:單線程收集器,在進(jìn)行垃圾收集時(shí),必須要暫停其他所有的工作線程,直到它收集結(jié)束。
需要STW(Stop The World),停頓時(shí)間長(zhǎng)。
簡(jiǎn)單高效,對(duì)于單個(gè)CPU環(huán)境而言,Serial收集器由于沒有線程交互開銷,可以獲取最高的單線程收集效率。
ParNew:是Serial的多線程版本,除了使用多線程進(jìn)行垃圾收集外,其他行為與Serial完全一樣
Tips:1.Server模式下虛擬機(jī)的首選新生收集器,與CMS進(jìn)行搭配使用。
Parallel Scavenge:目標(biāo)是達(dá)到一個(gè)可控制的吞吐量,吞吐量 = 運(yùn)行用戶代碼時(shí)間 / (運(yùn)行用戶代碼時(shí)間 + 垃圾收集時(shí)間),高吞吐量可以高效率地利用CPU時(shí)間,盡快完成程序的運(yùn)算任務(wù),主要適合在后臺(tái)運(yùn)算而不需要太多交互的任務(wù),并且虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控信息,動(dòng)態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時(shí)間或者最大的吞吐量,這種調(diào)節(jié)方式稱為GC自適應(yīng)調(diào)節(jié)策略。
Serial Old:老年代的單線程收集器,使用標(biāo)記 - 整理算法,
Parallel Old:老年代的多線程收集器,使用標(biāo)記 - 整理算法,吞吐量?jī)?yōu)先,適合于Parallel Scavenge搭配使用
CMS(Conrrurent Mark Sweep)收集器是以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。使用標(biāo)記 - 清除算法,收集過(guò)程分為如下四步:
初始標(biāo)記,標(biāo)記GCRoots能直接關(guān)聯(lián)到的對(duì)象,時(shí)間很短。
并發(fā)標(biāo)記,進(jìn)行GCRoots Tracing(可達(dá)性分析)過(guò)程,時(shí)間很長(zhǎng)。
重新標(biāo)記,修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄,時(shí)間較長(zhǎng)。
并發(fā)清除,回收內(nèi)存空間,時(shí)間很長(zhǎng)。
其中,并發(fā)標(biāo)記與并發(fā)清除兩個(gè)階段耗時(shí)最長(zhǎng),但是可以與用戶線程并發(fā)執(zhí)行
Tips:1. 對(duì)CPU資源非常敏感,可能會(huì)導(dǎo)致應(yīng)用程序變慢,吞吐率下降。
無(wú)法處理浮動(dòng)垃圾,因?yàn)樵诓l(fā)清理階段用戶線程還在運(yùn)行,自然就會(huì)產(chǎn)生新的垃圾,而在此次收集中無(wú)法收集他們,只能留到下次收集,這部分垃圾為浮動(dòng)垃圾,同時(shí),由于用戶線程并發(fā)執(zhí)行,所以需要預(yù)留一部分老年代空間提供并發(fā)收集時(shí)程序運(yùn)行使用。
由于采用的標(biāo)記 - 清除算法,會(huì)產(chǎn)生大量的內(nèi)存碎片,不利于大對(duì)象的分配,可能會(huì)提前觸發(fā)一次Full GC。虛擬機(jī)提供了-XX:+UseCMSCompactAtFullCollection參數(shù)來(lái)進(jìn)行碎片的合并整理過(guò)程,這樣會(huì)使得停頓時(shí)間變長(zhǎng),虛擬機(jī)還提供了一個(gè)參數(shù)配置,-XX:+CMSFullGCsBeforeCompaction,用于設(shè)置執(zhí)行多少次不壓縮的Full GC后,接著來(lái)一次帶壓縮的GC。
理解一下GC日志
1
[GC (System.gc()) [PSYoungGen: 6270K->584K(9216K)] 11390K->5712K(19456K), 0.0011969 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (System.gc())]與[Full GC (System.gc())],說(shuō)明垃圾收集的停頓類型,不是區(qū)分新生代GC和老年代GC的,如果有Full,則表示此次GC發(fā)生了Stop The World。
PSYoungGen: 6270K->584K(9216K),表示,新生代:該內(nèi)存區(qū)域GC前已使用容量 -> 該內(nèi)存區(qū)域GC后已使用容量(該內(nèi)存區(qū)域總?cè)萘浚?BR style='MAX-WIDTH: 100%; FONT-FAMILY: -apple-system, "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft Yahei", sans-serif; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 0px; PADDING-RIGHT: 0px; -webkit-font-smoothing: antialiased'>11390K->5712K(19456K),表示,GC前Java堆已使用的容量 -> GC后Java堆已使用的容量(Java堆總?cè)萘浚?BR style='MAX-WIDTH: 100%; FONT-FAMILY: -apple-system, "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", "Microsoft Yahei", sans-serif; PADDING-BOTTOM: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 0px; PADDING-RIGHT: 0px; -webkit-font-smoothing: antialiased'>0.0011969 secs,表示GC所占用的時(shí)間,單位為秒。
[Times: user=0.00 sys=0.00, real=0.00 secs],表示GC的更具體的時(shí)間,user代表用戶態(tài)消耗的CPU時(shí)間,sys代表內(nèi)核態(tài)消耗的CPU時(shí)間,real代表操作從開始到結(jié)束所經(jīng)過(guò)的墻鐘時(shí)間。CPU時(shí)間與墻鐘時(shí)間的區(qū)別是,墻鐘時(shí)間包括各種非運(yùn)算的等待耗時(shí),如等待磁盤IO,等待線程阻塞,CPU時(shí)間則不包含這些耗時(shí)。當(dāng)系統(tǒng)有多CPU或者多核時(shí),多線程操作會(huì)疊加這些CPU時(shí)間,所以讀者看到user或者sys時(shí)間超過(guò)real時(shí)間也是很正常的
GC類型
Minor GC:指發(fā)生在新生代的垃圾收集動(dòng)作,非常頻繁,速度較快。
Major GC:指發(fā)生在老年代的GC,出現(xiàn)Major GC,經(jīng)常會(huì)伴隨一次Minor GC,同時(shí)Minor GC也會(huì)引起Major GC,一般在GC日志中統(tǒng)稱為GC,不頻繁。
Full GC:指發(fā)生在老年代和新生代的GC,速度很慢,需要Stop The World。
大對(duì)象直接進(jìn)入老年代:大對(duì)象就是大量連續(xù)內(nèi)存空間的Java對(duì)象,典型的就是很長(zhǎng)的字符串及數(shù)組。并且內(nèi)存超過(guò)虛擬機(jī)設(shè)置大對(duì)象的值;
長(zhǎng)期存活的對(duì)象進(jìn)入老年代:jvm給每個(gè)對(duì)象定義一個(gè)對(duì)象年齡計(jì)數(shù)器。如果eden出生并經(jīng)過(guò)第一次Minor GC后仍然存活并且能被Survivor容納的話,將被移動(dòng)到Survivor空間并將對(duì)象年齡設(shè)為1.對(duì)象在Survivor區(qū)每”熬過(guò)”一次Minor GC則年齡+1,當(dāng)年齡達(dá)到一定程度(默認(rèn)15歲),下一次將會(huì)被晉升老年代。
動(dòng)態(tài)對(duì)象年齡判定:為了更好的適應(yīng)內(nèi)存狀況。如果在Survivor空間中相同年齡的所有對(duì)象大小的綜合大于Survivor的一半,那么大于等于這個(gè)年齡的將被一起帶入老年代
Tips:研究代碼對(duì)象到底怎么回收請(qǐng)看Page:93(深入理解JVM虛擬機(jī)第二版)
空間分配擔(dān)保
虛擬機(jī)參數(shù)設(shè)置;
代碼的運(yùn)行參數(shù)設(shè)置為: -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
靜態(tài)分派與動(dòng)態(tài)分派
靜態(tài)分派
1
Map map=new HashMap();
Map(靜態(tài)類型,外觀類型接口類型(我習(xí)慣叫)):其變化僅在使用時(shí)發(fā)生,變量本身的靜態(tài)類型不會(huì)改變,并且最終的靜態(tài)類型是在編譯期可知的。
HashMap(實(shí)際類型):其變化的結(jié)果在運(yùn)行期才可確定,編譯器不編譯程序時(shí)并不知道一個(gè)對(duì)象的實(shí)際類型是什么。
所有依賴靜態(tài)類型來(lái)定位方法執(zhí)行版本的分派動(dòng)作稱為靜態(tài)分派。
①.靜態(tài)分派典型的應(yīng)用是方法重載,
②.靜態(tài)分派發(fā)生在編譯階段,因此確定靜態(tài)分派的動(dòng)作實(shí)際上不是由虛擬機(jī)來(lái)執(zhí)行的
③.對(duì)于方法參數(shù)的匹配也是根據(jù)變量的靜態(tài)類型來(lái)確定,在很多情況下根據(jù)參數(shù)的類型并不能找到唯一的方法調(diào)用,這個(gè)時(shí)候的處理方式是找到一個(gè)最合適的方法。比如:
public class OverLoad {
public static void sayHello(char arg) {
System.out.println("hello char");
}
public static void sayHello(int arg) {
System.out.println("hello int");
}
public static void sayHello(long arg) {
System.out.println("hello long");
}
public static void sayHello(Character arg) {
System.out.println("hello Character");
}
public static void sayHello(Serializable arg) {
System.out.println("hello Serializable");
}
public static void sayHello(Object arg) {
System.out.println("hello object");
}
public static void sayHello(char ...arg) {
System.out.println("hello arg...");
}
public static void main(String[] args) { sayHello('a'); }
}
從頭注解方法,結(jié)果會(huì)按順序輸出。
1、基本類型是重載按char->int->long->float->double->Character->Serializable(因?yàn)镃haracter實(shí)現(xiàn)了他)順序匹配的。
2、可變參數(shù)的重載優(yōu)先級(jí)是最低的。
Tips:如果出現(xiàn)了兩個(gè)參數(shù)分, 別為Serializable和Comparable(Character實(shí)現(xiàn)這兩個(gè)),編譯器無(wú)法確定自動(dòng)轉(zhuǎn)型那種類型。提示類型模糊拒絕編譯;
動(dòng)態(tài)分派
方法執(zhí)行會(huì)找到對(duì)應(yīng)的實(shí)際類型。
動(dòng)態(tài)加載
NB之處 不僅僅能實(shí)現(xiàn)別人的接口,也能實(shí)現(xiàn)自己的接口這樣相當(dāng)于 對(duì)象本身了,但是可以卻可以在方法執(zhí)行之前或之后搞事情了
**public class DynamicProxyTest {
interface IHello{
void sayHello();
}
static class Hello implements IHello{
@Override
public void sayHello(){
System.out.println("hello world");
}
}
static class DynamicProxy implements InvocationHandler{ Object originalObj; Object bind(Object originalObj){ this.originalObj = originalObj; return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass(), getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("welcome"); return method.invoke(originalObj, args); } } public static void main(String[] args) { /* 設(shè)置此系統(tǒng)屬性,讓JVM生成的Proxy類寫入文件.保存路徑為:com/sun/proxy(如果不存在請(qǐng)生工創(chuàng)建) */ System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); IHello hello = (IHello)new DynamicProxy().bind(new Hello()); hello.sayHello(); }
}**
System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”, “true”)->設(shè)置此系統(tǒng)屬性,讓JVM生成的Proxy類寫入文件.保存路徑為:com/sun/proxy(如果不存在請(qǐng)生工創(chuàng)建)
java逆向工具:為了解決把1.5中編寫的代碼放到1.4 1.3的環(huán)境部署使用的問題。比較出色的Retrotranslator
Java魔法糖
泛型與擦除
編譯后的字節(jié)碼文件中替換為原生類型,并且在相應(yīng)的位置插入強(qiáng)制轉(zhuǎn)換;
所以泛型遇到重載,不會(huì)執(zhí)行編譯;例如參數(shù)List和List編譯后的文件是一樣的所以你懂的;
public class Sugar {
//看bin目錄下的編譯文件;
public static void main(String[] args) {
//泛型 自動(dòng)裝箱,自動(dòng)拆箱,便利循環(huán),變長(zhǎng)參數(shù);
List<Integer> list= Arrays.asList(1,2,3,4);
int sum=0;
for (int integer : list) {
sum+=integer;
}
System.out.println(sum);
}
}
編譯后文件public class Sugar {
public Sugar() {
}
public static void main(String[] args) {
List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4)});
int sum = 0;
int integer;
for(Iterator var3 = list.iterator(); var3.hasNext(); sum += integer) {
integer = ((Integer)var3.next()).intValue();
}
System.out.println(sum);
}
}
自動(dòng)裝箱陷阱
高效并發(fā)
volatile型變量的特殊規(guī)則
當(dāng)定義為volatile之后具備兩種特性:
第一保證此變量對(duì)所有線程的可見性。當(dāng)一個(gè)線程修改了這個(gè)值,新值對(duì)于其他線程來(lái)說(shuō)立即可知;
第二:禁止指令重排序優(yōu)化;
volatile和普通變量性能幾乎沒有區(qū)別,比synchronized關(guān)鍵字快;
Java線程調(diào)度
主要兩種:協(xié)同式調(diào)度和搶占式調(diào)度
協(xié)同(不用):執(zhí)行時(shí)間由線程本身來(lái)控制。吧自己工作執(zhí)行完后主動(dòng)通知系統(tǒng)切換到另一個(gè)線程;
壞處:如果線程出現(xiàn)堵塞那么所有都堵塞了
搶占:系統(tǒng)分配時(shí)間,切換不由線程本身來(lái)決定
Thread.yield()可以讓出執(zhí)行時(shí)間.獲取時(shí)間則沒有辦法;
額外知識(shí) ++不是原子性,AtomicInteger CAS(原子性)來(lái)避免阻塞同步;
加Java架構(gòu)師進(jìn)階交流群獲取Java工程化、高性能及分布式、高性能、深入淺出。高架構(gòu)。
性能調(diào)優(yōu)、Spring,MyBatis,Netty源碼分析和大數(shù)據(jù)等多個(gè)知識(shí)點(diǎn)高級(jí)進(jìn)階干貨的直播免費(fèi)學(xué)習(xí)權(quán)限