導航:首頁 > 編程語言 > java重新載入類

java重新載入類

發布時間:2022-04-16 21:14:33

java編程細節 java是怎麼載入類的

一.載入 通過類的全限定名轉換為二進制位元組流,在jvm堆中生成代表這個Class的對象,作為方法區域的方法入口.
二.連接 1.驗證:驗證class的位元組流是否對jvm虛擬機造成傷害,是否符合jvm的規范,這里包含幾個驗證. 2.准備:為類的static變數賦初始值,其中不包含類其它實例成員的初始化. 3.解析:將常量池內的符號引用替換成直接引用三.初始化 這里是static{}塊,構造函數,代碼塊{}的執行過程.四.使用 對象的屬性,方法等調用操作.五.銷毀 jvm通過確定對象沒有引用後進行gc操作.

㈡ java重載和重寫的區別

首先我們來講講:重載(Overloading)

(1) 方法重載是讓類以統一的方式處理不同類型數據的一種手段。多個同名函數同時存在,具有不同的參數個數/類型。
重載Overloading是一個類中多態性的一種表現。

(2) Java的方法重載,就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。
調用方法時通過傳遞給它們的不同參數個數和參數類型來決定具體使用哪個方法, 這就是多態性。

(3) 重載的時候,方法名要一樣,但是參數類型和個數不一樣,返回值類型可以相同也可以不相同。無法以返回型別作為重載函數的區分標准。

然後我們再來談談 重寫(Overriding)

(1) 父類與子類之間的多態性,對父類的函數進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。
但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要採用方法的重寫。
方法重寫又稱方法覆蓋。

(2)若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數表,則新方法將覆蓋原有的方法。
如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。

(3)子類函數的訪問修飾許可權不能少於父類的;

㈢ java如何實現類載入

重新定義類載入器,也就是ClassLoader,覆蓋其中的一個方法findClass
例如,應用程序可以創建一個網路類載入器,從伺服器中下載類文件。示例代碼如下所示:

ClassLoader loader = new NetworkClassLoader(host, port);
Object main = loader.loadClass("Main", true).newInstance();
. . .

㈣ java 怎麼向getsystemclassloader中載入新的類

ClassLoader: ClassLoader是一個抽象類,一般的系統有一個預設的ClassLoader用來裝載Class, 用ClassLoader.getSystemClassLoader()可以得到。不過有時候為了安全或有其它的特殊需要可以自定義自己的ClassLoader來進行loader一些需要的Class, 比如有的產品它用了自己的ClassLoader可以指定Class只從它指定的特定的JAR文件裡面來loader,如果想通過覆蓋ClassPath方法來想讓它用Class是行不通的。 有興趣的可以參照Java API 的更詳細的用法說明。

㈤ JAVA中如何重新載入.properties文件,使其他引用實時改變

*Spring提供的PropertiesLoaderUtils允許您直接通過基於類路徑的文件地址載入屬性資源

*最大的好處就是:實時載入配置文件,修改後立即生效,不必重啟

*/
privatestaticvoidspringUtil(){
Propertiesprops=newProperties();
while(true){
try{
props=PropertiesLoaderUtils.loadAllProperties("message.properties");
for(Objectkey:props.keySet()){
System.out.print(key+":");
System.out.println(props.get(key));
}
}catch(IOExceptione){
System.out.println(e.getMessage());
}
try{
Thread.sleep(5000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}

㈥ Java 類載入器怎麼實現將同一個對象載入兩次

類A中有一個欄位a,它的類型為X
類B中有一個欄位b,它的類型也為X
類A由classLoaderA所載入,類B由classLoaderB所載入
執行賦值語句A.a
=
B.b,由於這兩個類型均為X,可以執行,但是有一個要求,這個要求就是在A中所裝載類X的裝載器必須和在B中裝載類X的裝載器相同,否則賦值語句失敗!

㈦ java類載入順序

記住 3 條原則:
1、父類優先於子類
2、屬性優先於代碼塊優先於構造方法
3、靜態優先於非靜態
因此,類載入順序為:
父類靜態變數->父類靜態語句塊->子類靜態變數->子類靜態語句塊->父類普通成員變數->父類動態語句塊->父類構造器->子類普通成員變數->子類動態語句塊->子類構造器

㈧ java重新載入class文件

Java類的載入是動態的,它並不會一次性將所有類全部載入後再運行,而是保證程序運行的基礎類(像是基類)完全載入到jvm中,至於其他類,則在需要的時候才載入。這當然就是為了節省內存開銷。
Java的類載入器有三個,對應Java的三種類:
Bootstrap Loader // 負責載入系統類 (指的是內置類,像是String,對應於C#中的System類和C/C++標准庫中的類)
|
- - ExtClassLoader // 負責載入擴展類(就是繼承類和實現類)
|
- - AppClassLoader // 負責載入應用類(程序員自定義的類)
三個載入器各自完成自己的工作,但它們是如何協調工作呢?哪一個類該由哪個類載入器完成呢?為了解決這個問題,Java採用了委託模型機制。
委託模型機制的工作原理很簡單:當類載入器需要載入類的時候,先請示其Parent(即上一層載入器)在其搜索路徑載入,如果找不到,才在自己的搜索路徑搜索該類。這樣的順序其實就是載入器層次上自頂而下的搜索,因為載入器必須保證基礎類的載入。之所以是這種機制,還有一個安全上的考慮:如果某人將一個惡意的基礎類載入到jvm,委託模型機制會搜索其父類載入器,顯然是不可能找到的,自然就不會將該類載入進來。
我們可以通過這樣的代碼來獲取類載入器:
ClassLoader loader = ClassName.class.getClassLoader();
ClassLoader ParentLoader = loader.getParent();

注意一個很重要的問題,就是Java在邏輯上並不存在BootstrapKLoader的實體!因為它是用C++編寫的,所以列印其內容將會得到null。
前面是對類載入器的簡單介紹,它的原理機制非常簡單,就是下面幾個步驟:
1.裝載:查找和導入class文件;
2.連接:
(1)檢查:檢查載入的class文件數據的正確性;
(2)准備:為類的靜態變數分配存儲空間;
(3)解析:將符號引用轉換成直接引用(這一步是可選的)
3.初始化:初始化靜態變數,靜態代碼塊。
這樣的過程在程序調用類的靜態成員的時候開始執行,所以靜態方法main()才會成為一般程序的入口方法。類的構造器也會引發該動作。

㈨ 如何使用javassist修改已經載入的類的方法

參考手冊:

1、讀取和輸出位元組碼

ClassPool pool = ClassPool.getDefault();
//會從classpath中查詢該類
CtClass cc = pool.get("test.Rectangle");
//設置.Rectangle的父類
cc.setSuperclass(pool.get("test.Point"));
//輸出.Rectangle.class文件到該目錄中
cc.writeFile("c://");
//輸出成二進制格式
//byte[] b=cc.toBytecode();
//輸出並載入class 類,默認載入到當前線程的ClassLoader中,也可以選擇輸出的ClassLoader。
//Class clazz=cc.toClass();

這里可以看出,Javassist的載入是依靠ClassPool類,輸出方式支持三種。

2、新增Class
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass("Point");
//新增方法
cc.addMethod(m);
//新增Field
cc.addField(f);

從上面可以看出,對Class的修改主要是依賴於CtClass 類。API也比較清楚和簡單。

3、凍結Class
當CtClass 調用writeFile()、toClass()、toBytecode() 這些方法的時候,Javassist會凍結CtClass Object,對CtClass object的修改將不允許。這個主要是為了警告開發者該類已經被載入,而JVM是不允許重新載入該類的。如果要突破該限制,方法如下:
CtClasss cc = ...;
:
cc.writeFile();
cc.defrost();
cc.setSuperclass(...); // OK since the class is not frozen.

當 ClassPool.doPruning=true的時 候,Javassist 在CtClass object被凍結時,會釋放存儲在ClassPool對應的數據。這樣做可以減少javassist的內存消耗。默認情況 ClassPool.doPruning=false。例如

CtClasss cc = ...;
cc.stopPruning(true);
:
cc.writeFile(); // convert to a class file.
// cc沒有被釋放

提示:當調試時,可以調用debugWriteFile(),該方法不會導致CtClass被釋放。

4、Class 搜索路徑
從上面可以看出Class 的載入是依靠ClassPool,而ClassPool.getDefault() 方法的搜索Classpath 只是搜索JVM的同路徑下的class。當一個程序運行在JBoss或者Tomcat下,ClassPool Object 可能找到用戶的classes。Javassist 提供了四種動態載入classpath的方法。如下

//默認載入方式如pool.insertClassPath(new ClassClassPath(this.getClass()));
ClassPool pool = ClassPool.getDefault();

//從file載入classpath
pool.insertClassPath("/usr/local/javalib")

//從URL中載入
ClassPath cp = new URLClassPath("www.javassist.org", 80, "/java/", "org.javassist.");
pool.insertClassPath(cp);

//從byte[] 中載入
byte[] b = a byte array;
String name = class name;
cp.insertClassPath(new ByteArrayClassPath(name, b));

//可以從輸入流中載入class
InputStream ins = an input stream for reading a class file;
CtClass cc = cp.makeClass(ins);

5、ClassPool
5.1 減少內存溢出
ClassPool是一個CtClass objects的裝載容器。當載入了CtClass object後,是不會被ClassPool釋放的(默認情況下)。這個是因為CtClass object 有可能在下個階段會被用到。
當載入過多的CtClass object的時候,會造成OutOfMemory的異常。為了避免這個異常,javassist提供幾種方法,一種是在上面提到 的 ClassPool.doPruning這個參數,還有一種方法是調用 CtClass.detach()方法,可以把CtClass object 從ClassPool中移除。例如:
CtClass cc = ... ;
cc.writeFile();
cc.detach();

另外一中方法是不用默認的ClassPool即不用 ClassPool.getDefault()這個方式來生成。這樣當ClassPool 沒被引用的時候,JVM的垃圾收集會收集該類。例如
//ClassPool(true) 會默認載入Jvm的ClassPath
ClassPool cp = new ClassPool(true);
// if needed, append an extra search path by appendClassPath()

5.2 級聯ClassPools
javassist支持級聯的ClassPool,即類似於繼承。例如:
ClassPool parent = ClassPool.getDefault();
ClassPool child = new ClassPool(parent);
child.insertClassPath("./classes");

5.3 修改已有Class的name以創建一個新的Class
當調用setName方法時,會直接修改已有的Class的類名,如果再次使用舊的類名,則會重新在classpath路徑下載入。例如:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Point");
cc.setName("Pair");
//重新在classpath載入
CtClass cc1 = pool.get("Point");

對於一個被凍結(Frozen)的CtClass object ,是不可以修改class name的,如果需要修改,則可以重新載入,例如:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("Point");
cc.writeFile();
//cc.setName("Pair"); wrong since writeFile() has been called.
CtClass cc2 = pool.getAndRename("Point", "Pair");

6、Class loader
上面也提到,javassist同個Class是不能在同個ClassLoader中載入兩次的。所以在輸出CtClass的時候需要注意下,例如:

// 當Hello未載入的時候,下面是可以運行的。
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("Hello");
Class c = cc.toClass();

//下面這種情況,由於Hello2已載入,所以會出錯
Hello2 h=new Hello2();
CtClass cc2 = cp.get("Hello2");
Class c2 = cc.toClass();//這里會拋出java.lang.LinkageError 異常

//解決載入問題,可以指定一個未載入的ClassLoader
Class c3 = cc.toClass(new MyClassLoader());

6.1 使用javassist.Loader
從上面可以看到,如果在同一個ClassLoader載入兩次Class拋出異常,為了方便javassist也提供一個Classloader供使用,例如
ClassPool pool = ClassPool.getDefault();
Loader cl = new Loader(pool);
CtClass ct = pool.get("test.Rectangle");
ct.setSuperclass(pool.get("test.Point"));
Class c = cl.loadClass("test.Rectangle");
Object rect = c.newInstance();
:
為了方便監聽Javassist自帶的ClassLoader的生命周期,javassist也提供了一個listener,可以監聽ClassLoader的生命周期,例如:
//Translator 為監聽器
public class MyTranslator implements Translator {
void start(ClassPool pool)
throws NotFoundException, CannotCompileException {}
void onLoad(ClassPool pool, String classname)
throws NotFoundException, CannotCompileException
{
CtClass cc = pool.get(classname);
cc.setModifiers(Modifier.PUBLIC);
}
}
//示例
public class Main2 {
public static void main(String[] args) throws Throwable {
Translator t = new MyTranslator();
ClassPool pool = ClassPool.getDefault();
Loader cl = new Loader();
cl.addTranslator(pool, t);
cl.run("MyApp", args);
}
}
//輸出
% java Main2 arg1 arg2...

6.2 修改系統Class
由JVM規范可知,system classloader 是比其他classloader 是優先載入的,而system classloader 主要是載入系統Class,所以要修改系統Class,如果默認參數運行程序是不可能修改的。如果需要修改也有一些辦法,即在運 行時加入-Xbootclasspath/p: 參數的意義可以參考其他文件。下面修改String的例子如下:
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("java.lang.String");
CtField f = new CtField(CtClass.intType, "hiddenValue", cc);
f.setModifiers(Modifier.PUBLIC);
cc.addField(f);
cc.writeFile(".");
//運行腳本
% java -Xbootclasspath/p:. MyApp arg1 arg2...

6.3 動態重載Class
如果JVM運行時開啟JPDA(Java Platform Debugger Architecture),則Class是運行被動態重新載入的。具體方式可以參考java.lang.Instrument。javassist也提 供了一個運行期重載Class的方法,具體可以看API 中的javassist.tools.HotSwapper。

7、Introspection和定製
javassist封裝了很多很方便的方法以供使用,大部分使用只需要用這些API即可,如果不能滿足,Javassist也提供了一個低層的API(具體參考javassist.bytecode 包)來修改原始的Class。

7.1 插入source 文本在方法體前或者後
CtMethod 和CtConstructor 提供了 insertBefore()、insertAfter()和 addCatch()方法,它們可以插入一個souce文本到存在的方法的相應的位置。javassist 包含了一個簡單的編譯器解析這souce文本成二進制插入到相應的方法體里。
javassist 還支持插入一個代碼段到指定的行數,前提是該行數需要在class 文件里含有。
插入的source 可以關聯fields 和methods,也可以關聯方法的參數。但是關聯方法參數的時,需要在程序編譯時加上 -g 選項(該選項可以把本地變數的聲明保存在class 文件中,默認是不加這個參數的。)。因為默認一般不加這個參數,所以Javassist也提供了一些特殊的變數來代表方法參 數:$1,$2,$args...要注意的是,插入的source文本中不能引用方法本地變數的聲明,但是可以允許聲明一個新的方法本地變數,除非在程序 編譯時加入-g選項。
方法的特殊變數說明:
$0, $1, $2, ... this and actual parameters
$args An array of parameters. The type of $args is Object[].
$$ All actual parameters.For example, m($$) is equivalent to m($1,$2,...)
$cflow(...) cflow variable
$r The result type. It is used in a cast expression.
$w The wrapper type. It is used in a cast expression.
$_ The resulting value
$sig An array of java.lang.Class objects representing the formal parameter types
$type A java.lang.Class object representing the formal result type.
$class A java.lang.Class object representing the class currently edited.

7.1.1 $0, $1, $2, ...
$0代表的是this,$1代表方法參數的第一個參數、$2代表方法參數的第二個參數,以此類推,$N代表是方法參數的第N個。例如:
//實際方法
void move(int dx, int dy)
//javassist
CtMethod m = cc.getDeclaredMethod("move");
//列印dx,和dy
m.insertBefore("{ System.out.println($1); System.out.println($2); }");
注意:如果javassist改變了$1的值,那實際參數值也會改變。

7.1.2 $args
$args 指的是方法所有參數的數組,類似Object[],如果參數中含有基本類型,則會轉成其包裝類型。需要注意的時候,$args[0]對應的是$1,而不是$0,$0!=$args[0],$0=this。

7.1.3 $$
$$是所有方法參數的簡寫,主要用在方法調用上。例如:
//原方法
move(String a,String b)
move($$) 相當於move($1,$2)
如果新增一個方法,方法含有move的所有參數,則可以這些寫:
exMove($$, context) 相當於 exMove($1, $2, context)

7.1.4 $cflow
$cflow意思為控制流(control flow),是一個只讀的變數,值為一個方法調用的深度。例如:
//原方法
int fact(int n) {
if (n <= 1)
return n;
else
return n * fact(n - 1);
}

12 import

㈩ java運行顯示「找不到或無法載入主類」!

該如何解決呢?解決辦法如下:

1.由於是在運行階段出現的問題,那麼可能是環境變數配置不當的問題,即可能是classpath路徑配置錯誤,而導致.class文件無法載入。那麼此時你可以檢查是否配置好classpath路徑,一般來說classpath路徑配置如下:

.;%java_home%lib;%java_home%lib ools.jar; (注意前面的 . 以及 ; 缺一不可)

其中.表示當前路徑,;表示分隔符。

2.如果你試過了很多次,classpath也配置對了,依舊出現這個錯誤,注意你使用的測試代碼,是否在某一個包名的下面;

比如說如下測試代碼:

在文件所在的當前目錄下,運行javac TestPlusPlus.java編譯成功,生成TestPlusPlus.class文件,這個時

候,你用javaTestPlusPlus想運行程序,總會出現」找不到或無法載入主類「的錯誤。這個時候要注意,

之所以找不到,是因為TestPlusPlus在HelloWorld包名的下面。

解決辦法:

1.去掉 」packageHelloWorld;「 重新用javac 編譯TestPlusPlus.java,再運行javaTestPlusPlus就可以了。

2.新建一個包名一樣的文件夾,在本例中,為建立一個HelloWorld的文件夾,把TestPlusPlus.java文件移到該目錄下。

然後在HelloWorld文件夾的平級下,打開DOS命令窗口,運行javacHelloWorld/TestPlusPlus.java編譯程序,

運行javaHelloWorld/TestPlusPlus(或者javaHelloWorld.TestPlusPlus也可以),則可以運行含有包名的java程序。

注意:包名不要含有'.'(點),' '(空格)等特殊符號,這樣的話命令行無法判斷包名與java程序名的分割點在哪裡,

從而還是找到或者無法載入主類。

原理說明:

java程序運行class文件,對於有包名的類,java把包名當成文件夾處理."包名+類名"相當於"文件夾目錄+類名"來尋找類。

閱讀全文

與java重新載入類相關的資料

熱點內容
基於滑動窗口計演算法 瀏覽:209
國家python發展 瀏覽:296
忘記加密密碼後該如何解開 瀏覽:711
python開發文件伺服器 瀏覽:348
重啟svn命令 瀏覽:597
python組合數據類型題庫解析 瀏覽:76
電腦解壓文件的安裝包 瀏覽:467
不培訓能幹程序員嗎 瀏覽:281
編譯器怎麼分享微信 瀏覽:797
四川加密防塵網廠 瀏覽:284
列印機怎麼連上伺服器 瀏覽:618
2k20解壓後不能進去 瀏覽:190
伺服器掉線後顯示什麼 瀏覽:206
python根據經緯度獲取國家 瀏覽:47
stop伺服器有什麼作用 瀏覽:586
雲伺服器集群游戲伺服器 瀏覽:546
澪pro點伺服器閃退怎麼回事 瀏覽:855
同城砍票在APP哪裡找 瀏覽:574
c反匯編與逆向分析技術揭秘pdf 瀏覽:392
皮革pdf 瀏覽:221