創(chuàng)建可執(zhí)行的 JAR 文件包
孫吳網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、自適應網(wǎng)站建設等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)自2013年起到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選成都創(chuàng)新互聯(lián)。
制作一個可執(zhí)行的 JAR 文件包來發(fā)布你的程序是 JAR 文件包最典型的用法。
Java 程序是由若干個 .class 文件組成的。這些 .class 文件必須根據(jù)它們所屬的包不同而分級分目錄存放;運
行前需要把所有用到的包的根目錄指定給 CLASSPATH 環(huán)境變量或者 java 命令的 -cp 參數(shù);運行時還要到控制臺下
去使用 java 命令來運行,如果需要直接雙擊運行必須寫 Windows 的批處理文件 (.bat) 或者 Linux 的 Shell 程序。
因此,許多人說,Java 是一種方便開發(fā)者苦了用戶的程序設計語言。
其實不然,如果開發(fā)者能夠制作一個可執(zhí)行的 JAR 文件包交給用戶,那么用戶使用起來就方便了。在 Windows 下
安裝 JRE (Java Runtime Environment) 的時候,安裝文件會將 .jar 文件映射給 javaw.exe 打開。那么,對于一個
可執(zhí)行的 JAR 文件包,用戶只需要雙擊它就可以運行程序了,和閱讀 .chm 文檔一樣方便 (.chm 文檔默認是由
hh.exe 打開的)。那么,現(xiàn)在的關(guān)鍵,就是如何來創(chuàng)建這個可執(zhí)行的 JAR 文件包。
創(chuàng)建可執(zhí)行的 JAR 文件包,需要使用帶 cvfm 參數(shù)的 jar 命令,同樣以上述 test 目錄為例,命令如下:
jar cvfm test.jar manifest.mf test
這里 test.jar 和 manifest.mf 兩個文件,分別是對應的參數(shù) f 和 m,其重頭戲在 manifest.mf。因為要創(chuàng)建可
執(zhí)行的 JAR 文件包,光靠指定一個 manifest.mf 文件是不夠的,因為 MANIFEST 是 JAR 文件包的特征,可執(zhí)行的
JAR 文件包和不可執(zhí)行的 JAR 文件包都包含 MANIFEST。關(guān)鍵在于可執(zhí)行 JAR 文件包的 MANIFEST,其內(nèi)容包含了
Main-Class 一項。這在 MANIFEST 中書寫格式如下:
Main-Class: 可執(zhí)行主類全名(包含包名)
例如,假設上例中的 Test.class 是屬于 test 包的,而且是可執(zhí)行的類
(定義了 public static void main(String[]) 方法),那么這個 manifest.mf 可以編輯如下:
Main-Class: test.Test 回車
這個 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且該
行以一個回車符結(jié)束即可。創(chuàng)建了 manifest.mf 文件之后,我們的目錄結(jié)構(gòu)變?yōu)椋?/p>
==
|-- test
| `-- Test.class
`-- manifest.mf
這時候,需要到 test 目錄的上級目錄中去使用 jar 命令來創(chuàng)建 JAR 文件包。也就是在目錄樹中使用“==”表
示的那個目錄中,使用如下命令:
jar cvfm test.jar manifest.mf test
之后在“==”目錄中創(chuàng)建了 test.jar,這個 test.jar 就是執(zhí)行的 JAR 文件包。運行時只需要使用
java -jar test.jar 命令即可。
需要注意的是,創(chuàng)建的 JAR 文件包中需要包含完整的、與 Java 程序的包結(jié)構(gòu)對應的目錄結(jié)構(gòu),就像上例一樣。
而 Main-Class 指定的類,也必須是完整的、包含包路徑的類名,如上例的 test.Test;而且在沒有打成 JAR 文件包
之前可以使用 java 類名 來運行這個類,即在上例中 java test.Test 是可以正確運行的 (當然要在 CLASSPATH
正確的情況下)。
(忘記從哪兒下的了??!可能不太全??!)
Web容器啟動后執(zhí)行代碼的幾種方式
其執(zhí)行順序為:
4===5===1===2===3
即指定init-method的Bean開始執(zhí)行
接著實現(xiàn)spring的Bean后置處理器開始執(zhí)行
然后是Servlet的監(jiān)聽器執(zhí)行
再接下來是Servlet的過濾器執(zhí)行
最后才是Servlet執(zhí)行
1、實現(xiàn)Servlet監(jiān)聽器接口ServletContextListener
[java] view plain copy
public class InitListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent context) {
}
@Override
public void contextInitialized(ServletContextEvent context) {
// 上下文初始化執(zhí)行
System.out.println("================[ServletContextListener]自動加載啟動開始.");
SpringUtil.getInstance().setContext(
span style="white-space:pre" /spanWebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext())
span style="white-space:pre" /span);
}
}
然后在web.xml文件配置該監(jiān)聽器
[html] view plain copy
listener
listener-classcom.test.init.InitListener/listener-class
/listener
2、實現(xiàn)Servlet的過濾器Filter
[html] view plain copy
public class InitFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException,
ServletException {
}
@Override
public void init(FilterConfig config) throws ServletException {
System.out.println("================[Filter]自動加載啟動開始.");
// 讀取Spring容器中的Bean[此時Bean已加載,可以使用]
//寫啟動需要執(zhí)行的代碼
System.out.println("================[Filter]自動加載啟動結(jié)束.");
}
}
然后在web.xml文件配置過濾器即可
[html] view plain copy
filter
filter-nameInitFilter/filter-name
filter-classcom.test.init.InitFilter/filter-class
/filter
filter-mapping
filter-nameInitFilter/filter-name
url-pattern//url-pattern
/filter-mapping
3、編寫一個Servlet,在web.xml里面配置容器啟動后執(zhí)行即可
[html] view plain copy
public class InitServlet extends HttpServlet {
/**
*/
private static final long serialVersionUID = 1L;
@Override
public void init(ServletConfig config) {
try {
super.init();
} catch (ServletException e) {
e.printStackTrace();
}
System.out.println("================[Servlet]自動加載啟動開始.");
// 讀取Spring容器中的Bean[此時Bean已加載,可以使用]
//執(zhí)行想要的代碼
System.out.println("================[Servlet]自動加載啟動結(jié)束.");
}
}
然后在web.xml文件配置該Servlet的啟動方式為:容器啟動后執(zhí)行
servlet
servlet-nameInitServlet/servlet-name
servlet-classcom.test.init.InitServlet/servlet-class
init-param
param-nameusername/param-name
param-valuetest/param-value
/init-param
!-- 此處指定加載順序為2,表明還有優(yōu)先級更高的Servlet要先執(zhí)行 --
load-on-startup2/load-on-startup
/servlet
servlet-mapping
servlet-nameInitServlet/servlet-name
url-pattern//url-pattern
/servlet-mapping
關(guān)于啟動后執(zhí)行,由load-on-startup指定:
(1)當值為0或者大于0時,表示容器在應用啟動時就加載這個servlet。值越小,啟動優(yōu)先級越高;
(2)當是一個負數(shù)時或者沒有指定時,表示該servlet被調(diào)用時才加載。
4、如果你使用Spring IOC作為Bean管理容器,那么可以指定init-method其中init-method表示bean加載成功后,立即執(zhí)行某個方法。配置如下:start為要執(zhí)行的方法名稱
[html] view plain copy
!-- service --
bean id="shopService" class="com.test.teach.service.ShopService" span style="color:#33ffff;"init-method="start"/span
property name="shopDao" ref="shopDao" /
/bean
此代碼注入非依賴注入,是hack里的?代碼注入
場景是這樣滴:
機器上有一個java進程,我不想停止它,但我想把一段代碼植入進去,干
一些事情(獲取一些信息,改變一些值,監(jiān)控一些東西,或者其它猥瑣的事情)
這個進程不能停,而且也沒有預料到現(xiàn)在的事情,或者這個進程的代碼完全不能修改。
好,這篇文章是要干這個事情,它基于?jvm的?jdi或者jvmti?接口
這里用的jvmti,jdi也可以,麻煩不少
應該jdk1.5?就有,需要用c寫。1.6?支持另一種方式,java也可以寫
以前做過類似的事情,代碼找不到了,現(xiàn)在有實現(xiàn)了一番。
直接上代碼:
被注入的代碼是這樣滴:
while(true) {
System.out.println(System.currentTimeMillis());
Thread.sleep(1000);
}
每隔一秒輸出當前時間,只是示意用。不管什么java程序都行
我要注入的類,那個方法是固定的:
package com.zms.inject;
import java.lang.instrument.Instrumentation;
public class MyAgent1 {
public static void premain(String s) {
premain(s, null);
}
public static void premain(String s, Instrumentation instru) {
System.out.println("I'm injected! 木哈哈哈哈哈");
System.out.printf("param: %s\n", s);
}
public static void agentmain(String args, Instrumentation inst) {
premain(args, inst);
}
public static void agentmain(String args) {
premain(args);
}
}
編譯,打入jar包
MANIFEST.MF
Manifest-Version:?1.0
Created-By:?1.6.0_26?(Apple?Inc.)
Agent-Class:?com.zms.inject.MyAgent1
Premain-Class:?com.zms.inject.MyAgent1
操作代碼:
import com.sun.tools.attach.*;
import com.sun.tools.attach.spi.AttachProvider;
VirtualMachine vm=VirtualMachine.attach("24862"); //target java process pid
System.out.println(vm);
vm.loadAgent("/Users/zms/workspace/mt/out/production/agent1.jar","Powered by zms!");
Thread.sleep(1000);
vm.detach();
目標程序結(jié)果:?
1317283652520
1317283653520
1317283654521
I'm?injected!?木哈哈哈哈哈
param:?Powered?by?zms!
1317283655521
1317283656522