Java中如何修改Jar中的内容[转载]

1.这篇文章讲了一种曲折的方式来修改jar中的字节码. 比较有趣,可以用来参考.原文链接:http://blog.csdn.net/jiangwei0910410003/article/details/45600385

如果原文链接可达推荐跳往原文链接阅读,有更好的界面布局.

2. 对于直接修改字节码,可以看我之前发表的文章: http://ieroot.com/2014/02/11/1435.html

############### Java中如何修改Jar中的内容 [转载]############

一、摘要

好长时间没写blog了,之前换了一家公司。表示工作更有战斗力了,可惜就是没时间写文章了。在这段时间其实是遇到很多问题的,只是都是记录下来,并没有花时间去研究解决。但是这周遇到这个问题没办法让我继续前进了。必须记录一下。以被后人使用。不多说了,进入主题。

二、前提

1、对于GA的了解(自行google)

2、对CampaignTrackingReceiver类的了解,他是当从GP上下载并且安装完成一个app的时候,发送一个广播,会在Intent中携带一些数据,一般是Refer值,这里可以区分从哪里下载的,具体简单的例子:A应用是我需要发布到GP上的应用,但是我们可能会在各个渠道上推广A,所以我们可能需要加上渠道号进行统计,所以这时候需要在A应用添加CampaignTrackingReceiver广播接收器,然后处理接收到的广播中的Intent的内容,解析出具体的渠道号,进行上报即可。所以说GP发送这个广播还是很奇特的,他发送了这个广播,然后等我们安装A并且运行了之后就可以接收到这个广播,等于这个广播发出去了,他会等待有一个接收器接受他。

3、本文中需要用到的工具下载地址:http://download.csdn.net/detail/jiangwei0910410003/8679153,下载完之后,首先要看一下txt文档中的说明。

三、问题描述

工程中接入了GA统计(Google提供的一种app统计功能的SDK),但是我们自己可能需要统计app从GP上下载的统计(这里一般是注册一个CampaignTrackingReceiver的广播),但是有问题就是GA的SDK中已经包含了CampaignTrackingReceiver类了,当时在弄的时候进入到了一个误区:就是认为如果app中想接收到这个广播的话。广播接收器的包名必须是:com.google.analytics.tracking.android,类名:CampaignTrackingReceiver,类似于下面的注册代码:

[html] view plaincopy

  1. <receiver  
  2.     android:name=“com.google.analytics.tracking.android.CampaignTrackingReceiver”  
  3.     android:exported=“true”>  
  4.     <intent-filter>  
  5.         <action android:name=“com.android.vending.INSTALL_REFERRER” />  
  6.     </intent-filter>  
  7. </receiver>  

但是之后发现不需要这样的,只要包名一样即可,其实从Android中发送广播的机制就可以知道。类名没有关系的,但是当时这个东西没办法测试的(需要发布一个测试app到GP上,时间上也是不允许的,只能听前辈的)。最后也是自己发布了一个测试app测试了才知道,不需要类名一样的,这个也算是一种收获,那么既然类名不一样的话,这里就没有问题了。就不会和GA中的类重复了。但是我在没有解释这个误区前用了另外的一种方法解决了这个问题。既然GA中有这个广播接收类,我们不能定义的话,可以在它的SDK中的这个广播类中插入一段代码:发送一个广播,把Intent中的数据带出来即可。思路有了,下面来看一下具体操作:

四、技术介绍

下面讲述的内容是基于上面的误区没有被解释的情况下说的,而且侧重点也不是解释误区。而是如何修改Jar中内容

首先说一下这个过程中的三个角色:jar,dex,smali

四个工具:dx.bat,dex2jar.bat,baksmali.jar,smali.jar

关系图如下:

我们这里需要修改jar中的代码,

首先说明一下,关于修改jar中的代码其实有很多方法的:

1、直接用压缩包工具打开jar中的class文件进行修改(除非你对指令集很熟悉,反正我是不愿意尝试)

2、使用jd-gui工具直接打开jar,进行修改(这个虽然能看懂代码,但是有一个问题就是如果代码被混淆了,那个难度还不如第一种方法了,所以也没有尝试)

好吧,那么第三种方法就是修改smali文件,这个文件的好处在于:指令简单,而且如果混淆了,也是没有关系的。关于smail的指令说明,可以自行google一下。很简单这里就不做解释了。

那么问题来了,如何将jar变成smali呢?这里没有发现他们两之间的直接转化工具,所以就曲线救国的方式做了。

首先将jar==>dex==>smali

然后修改smail中的内容

修改完之后会变成jar

smail==>dex==>jar

相当于dex是中转站了。

五、项目演示

技术实现说明完之后,下面来看一下Demo:

ReceiverLib工程

1、BtnReceiver.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.util.Log;  
  7.   
  8. public class BtnReceiver extends BroadcastReceiver{  
  9.   
  10.     private String action = “demo.action.myreceiver”;  
  11.       
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         Log.i(“demo”“action:”+intent.getAction());  
  15.     }  
  16.   
  17. }  

接收到广播然后打印log一下

2、MyReceiver.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.util.Log;  
  7.   
  8. public class MyReceiver extends BroadcastReceiver{  
  9.   
  10.     private String action = “demo.action.myreceiver”;  
  11.       
  12.     @Override  
  13.     public void onReceive(Context context, Intent intent) {  
  14.         Log.i(“demo”“action:”+intent.getAction());  
  15.     }  
  16.   
  17. }  

3、Utils.java

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.content.Context;  
  4. import android.content.Intent;  
  5.   
  6. public class Utils {  
  7.       
  8.     public static void sendBroadcast(Context context,String action){  
  9.         Intent intent = new Intent();  
  10.         intent.setAction(action);  
  11.         context.sendBroadcast(intent);  
  12.     }  
  13.   
  14. }  

说明:BtnReceiver是点击Button之后发送的一个模拟广播,相当于上面需要改的CampaignTrackingReceiver类,MyReceiver是我们需要自己添加的广播接收器。

项目下载:http://download.csdn.net/detail/jiangwei0910410003/8679113

ReceiverDemo工程(需要导入ReceiverLib导出的jar)

[java] view plaincopy

  1. package com.example.receiverdemo;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v7.app.ActionBarActivity;  
  5. import android.view.View;  
  6. import android.view.View.OnClickListener;  
  7.   
  8. public class MainActivity extends ActionBarActivity {  
  9.       
  10.     private String action = “demo.action.btnreceiver”;  
  11.   
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.activity_main);  
  16.         findViewById(R.id.btn).setOnClickListener(new OnClickListener(){  
  17.             @Override  
  18.             public void onClick(View v) {  
  19.                 Utils.sendBroadcast(MainActivity.this, action);  
  20.             }});  
  21.     }  
  22. }  

模拟发送一个广播

项目下载:http://download.csdn.net/detail/jiangwei0910410003/8679123

效果:

点击Button之后,发送了广播,BtnReceiver也接收到了。

那么下面就开始在BtnReceiver.java中插入代码,发送一个MyReceiver

首先使用dx命令,将我们上面ReceiverLib导出的jar变成dex文件:

dx命令的使用方式:dx –dex –output C:\receiver.dex receiver.jar

然后在将receiver.dex转化成smali:

baksmali.jar的使用方式:java -jar baksmali-2.0.5.jar -o c:\classout/ c:\receiver.dex 

我们可以查看smali文件,我们重点看BtnReceiver.smali文件,因为我们要在这里插入代码:

[java] view plaincopy

  1. .class public Lcom/example/receiverdemo/BtnReceiver;  
  2. .super Landroid/content/BroadcastReceiver;  
  3. .source “BtnReceiver.java”  
  4.   
  5.   
  6. # direct methods  
  7. .method public constructor <init>()V  
  8.     .registers 1  
  9.   
  10.     .prologue  
  11.     .line 8  
  12.     invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V  
  13.   
  14.     returnvoid  
  15. .end method  
  16.   
  17.   
  18. # virtual methods  
  19. .method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V  
  20.     .registers 7  
  21.     .param p1, “context”    # Landroid/content/Context;  
  22.     .param p2, “intent”    # Landroid/content/Intent;  
  23.   
  24.     .prologue  
  25.     .line 12  
  26.     invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;  
  27.   
  28.     move-result-object v0  
  29.   
  30.     .line 13  
  31.     .local v0, “action”:Ljava/lang/String;  
  32.     const-string v1, “demo”  
  33.   
  34.     new-instance v2, Ljava/lang/StringBuilder;  
  35.   
  36.     const-string v3, “action:”  
  37.   
  38.     invoke-direct {v2, v3}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V  
  39.   
  40.     invoke-virtual {v2, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;  
  41.   
  42.     move-result-object v2  
  43.   
  44.     invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;  
  45.   
  46.     move-result-object v2  
  47.   
  48.     invoke-static {v1, v2}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I  
  49.   
  50.     const-string v4, “demo.action.myreceiver”  
  51.   
  52.     invoke-static {p1, v4}, Lcom/example/receiverdemo/Utils;->sendBroadcast(Landroid/content/Context;Ljava/lang/String;)V  
  53.   
  54.     const-string v5, “sendbroadcast”  
  55.   
  56.     invoke-static {v1, v5}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I  
  57.   
  58.     .line 14  
  59.     returnvoid  
  60. .end method  

关于smali指令网上自行搜索,很简单的,我们需要插入一行代码就是:

Utils.sendBroadcast方法:

这个过程中没有难度的,就不做解释了

下面我们就需要还原成jar了:

使用smali.jar工具将samli变成dex

用法:java -jar smali-2.0.5.jar c:\classout/ -o c:\receiver.dex

然后使用dex2jar命令将dex变成jar

用法:dex2jar receiver.dex

这时候我们就产生了修改之后的jar,我们将这个jar替换ReceiverDemo中的jar,然后运行结果:

成功显示了。我们的MyReceiver接收到了BtnReceiver中发送出来的广播了。

问题:

在这个过程中可能使用一些命令的时候会出现问题:

这个是class版本号不对,需要修改一下Eclipse中的Java编译器版本在编译导出jar就可以了。

其他的问题我这里没有遇到了。如果在开发的过程中遇到问题,记得回复留言,我尽量解答一下~~

六、总结

1、关于上面说到的问题,就是GA包中的类重复的问题,再次在说明一下,那个是个误区,我们自定一个Receiver也是可以的,不需要类名必须是:CampaignTrackingReceiver,所以有同学如果用到这个类的话,一定要记得,不要在入这个误区了。

2、关于修改jar中的内容,其实用途还是很多的,但是不是正规的解决方法,这个有点偏向于破解的方向了,这个是不符合开发原则的,这里说明一下就是为了多一条解决问题的办法,而且对逆向领域的一种知识补充,这个内容对逆向领域用处还是很大的。

3、关于这种方式使用与所有Java编写的程序,这里可能偏向于Android移动端了,但是如果JavaWeb中遇到这样的问题,也是可以使用这种方式解决的,不仅仅局限于Android方向。

Compile java projects using javac command

I downloaded a java project from github today, which seems an eclipse project. But do not want to import into eclipse to compile and pack it because it will let my workspace mass. So I struggled to compile it with java and javac commands on terminal.

The file tree looked as this :

$ tree
.
├── README.md
├── jars
│   ├── commons-codec-1.6.jar
│   ├── commons-logging-1.1.3.jar
│   ├── fluent-hc-4.3.3.jar
│   ├── httpclient-4.3.3.jar
│   ├── httpclient-cache-4.3.3.jar
│   ├── httpcore-4.3.2.jar
│   ├── httpmime-4.3.3.jar
│   ├── jsoup-1.7.2.jar
│   └── mysql-connector-java-5.1.22-bin.jar
├── pic
│   ├── pic.jpg
│   ├── pic2.fla
│   ├── pic2.jpg
│   ├── pic3.jpg
│   └── pic4.jpg
└── src
└── com
└── td1madao
├── bean
│   ├── JsoupBean.java
│   ├── KeyWord.java
│   └── UrlScoreBean.java
├── db
│   └── DBOperator.java
├── filters
│   ├── FiltTag.java
│   ├── URLTool.java
│   └── fetchUrlUtil.java
├── global
│   ├── GlobalVar.java
│   └── TaskQueue.java
├── gui
│   ├── MyFrame.java
│   └── NoGui.java
├── htmlGet
│   └── GetHttp.java
├── math
│   ├── ListProcess.java
│   └── WordDensity.java
├── stringUtil
│   └── MyStringUtil.java
├── threads
│   ├── DaemonThread.java
│   ├── MEngine.java
│   ├── MSpider.java
│   └── SpiderUtil.java
└── useEngine
├── CopyOfFetchSouSou.java
├── Fetch360.java
├── FetchBaidu.java
├── FetchGoogle.java
└── FetchSouSou.java
15 directories, 39 files

To compile this project , I used the command as shown below:

 

javac `find . -type f -name "[!^Copy]*.java"` -encoding GBK -cp .:jars/* -d classes/
`find . -type f -name "[!^Copy]*.java"`

list all the java files in the sub-directories from the current.

-encoding GBK

switch specifics source code encoding.

-cp .:jars/*

specifics the classpath, : is used to append paths together.

-d classes/

specifics which directory to generate the target class files.

After the command, the file tree was like this:

$ tree
.
├── README.md
├── classes
│   └── com
│       └── td1madao
│           ├── bean
│           │   ├── JsoupBean.class
│           │   ├── KeyWord.class
│           │   └── UrlScoreBean.class
│           ├── db
│           │   └── DBOperator.class
│           ├── filters
│           │   ├── FiltTag.class
│           │   ├── URLTool.class
│           │   └── fetchUrlUtil.class
│           ├── global
│           │   ├── GlobalVar.class
│           │   └── TaskQueue.class
│           ├── gui
│           │   ├── MyFrame$1.class
│           │   ├── MyFrame$2.class
│           │   ├── MyFrame$3.class
│           │   ├── MyFrame$4.class
│           │   ├── MyFrame$5.class
│           │   ├── MyFrame$6.class
│           │   ├── MyFrame.class
│           │   └── NoGui.class
│           ├── htmlGet
│           │   └── GetHttp.class
│           ├── math
│           │   ├── ListProcess.class
│           │   └── WordDensity.class
│           ├── stringUtil
│           │   └── MyStringUtil.class
│           ├── threads
│           │   ├── DaemonThread.class
│           │   ├── MEngine.class
│           │   ├── MSpider.class
│           │   └── SpiderUtil.class
│           └── useEngine
│               ├── Fetch360.class
│               ├── FetchBaidu.class
│               ├── FetchGoogle.class
│               └── FetchSouSou.class
├── jars
│   ├── commons-codec-1.6.jar
│   ├── commons-logging-1.1.3.jar
│   ├── fluent-hc-4.3.3.jar
│   ├── httpclient-4.3.3.jar
│   ├── httpclient-cache-4.3.3.jar
│   ├── httpcore-4.3.2.jar
│   ├── httpmime-4.3.3.jar
│   ├── jsoup-1.7.2.jar
│   └── mysql-connector-java-5.1.22-bin.jar
├── pic
│   ├── pic.jpg
│   ├── pic2.fla
│   ├── pic2.jpg
│   ├── pic3.jpg
│   └── pic4.jpg
└── src
    └── com
        └── td1madao
            ├── bean
            │   ├── JsoupBean.java
            │   ├── KeyWord.java
            │   └── UrlScoreBean.java
            ├── db
            │   └── DBOperator.java
            ├── filters
            │   ├── FiltTag.java
            │   ├── URLTool.java
            │   └── fetchUrlUtil.java
            ├── global
            │   ├── GlobalVar.java
            │   └── TaskQueue.java
            ├── gui
            │   ├── MyFrame.java
            │   └── NoGui.java
            ├── htmlGet
            │   └── GetHttp.java
            ├── math
            │   ├── ListProcess.java
            │   └── WordDensity.java
            ├── stringUtil
            │   └── MyStringUtil.java
            ├── threads
            │   ├── DaemonThread.java
            │   ├── MEngine.java
            │   ├── MSpider.java
            │   └── SpiderUtil.java
            └── useEngine
                ├── CopyOfFetchSouSou.java
                ├── Fetch360.java
                ├── FetchBaidu.java
                ├── FetchGoogle.java
                └── FetchSouSou.java

28 directories, 68 files


Now, we can execute the compiled project already, with this command:


java -cp classes com.td1madao.gui.MyFrame

Now I want to pack these class files together to be a jar file, so that, it will look good and easy to move.

with these commands:


cd classes;
jar cvf mspider *

To run with this command:


java -cp mspider.jar com.td1madao.gui.MyFrame

This all.

keystore提取私钥和证书

这篇文章讲解了:

(1). 如何从keystore中提取私钥和证书

(2). 使用私钥/公钥加密一段文本的方法

(3). 使用私钥/公钥解密密文的方法

(4). 通过私钥加密公钥解密的方式验证公钥/私钥是否正确的方法

 

原文链接: http://www.360doc.com/content/11/1226/02/3700464_174996042.shtml

 

keystore提取私钥和证书(重要×××)

2011-04-23 13:30:37|  分类: HTTPS keytool |字号 订阅

( From:http://wangxuliangboy.javaeye.com/blog/382434)

 

keytool -genkey -alias test -keyalg RSA -keystore c:/key.store

生成keyStore

RSA是一个既能用于数据加密也能用于数字签名的算法。

DSA(Digital Signature Algorithm,数字签名算法,用作数字签名标准的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。

提取证书:

通过keytool命令我们可以很轻松的提取证书.

证书包括主体信息,公钥.

keytool -export -alias 别名 -keystore 文件名 -file 证书名称

 

但是我们无法通过KEYTOOL工具来提取私钥的..我们只能通过java的KeyStore类getEntry() 或者getKey()来提取私钥.

 

读取keyStore文件:

char[] password = “password”.toCharArray();

java.io.FileInputStream fis = new java.io.FileInputStream(“c:/server/server_keystore”);

//   从指定的输入流中加载此 KeyStore
ks.load(fis, password);
//keystore 中的每一项都用“别名”字符串标识。

//使用指定保护参数获取指定别名的 keystore Entry

//KeyStore.PrivateKeyEntry   保存 PrivateKey 和相应证书链的 KeyStore 项。

方法1. KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(
“keystore别名”,
new KeyStore.PasswordProtection(
password));

 

//   返回与给定别名相关联的密钥

方法2. PrivateKey key = (PrivateKey) ks.getKey(“ser”, password);

 

怎么来验证提取的私钥是否正确呢?(因为公钥私钥必须成对出现,我们可以通过证书提取去公钥,然后用公钥加密,使用刚刚获得的私钥解密)

 

提取证书的方法:

keytool -export -alias 别名 -keystore 文件名 -file 证书名称

// 提取公钥方法1:通过PrivateKeyEntry获得证书,然后提取公钥

Certificate c = pkEntry.getCertificate();
PublicKey publicKey = c.getPublicKey();

 

 

// 提取公钥方法2:通过证书流获得证书,然后提取公钥

CertificateFactory cf = CertificateFactory.getInstance(“X.509”);
FileInputStream in = new FileInputStream(“C:\\server\\server.cer”);

//生成一个证书对象并使用从输入流 inStream 中读取的数据对它进行初始化。
Certificate c = cf.generateCertificate(in);
PublicKey publicKey = c.getPublicKey();

// 提取公钥方法3:通过别名获得证书,然后提取公钥

Certificate c = ks.generateCertificate(“ser”); // 通过别名来提取公钥
PublicKey publicKey = c.getPublicKey();

 

 

 

//通过下面这段代码提取的私钥是否正确

String before = “asdf”;

byte[] plainText = before.getBytes(“UTF-8”);
Cipher cipher = Cipher.getInstance(“RSA/ECB/PKCS1Padding”);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 用公钥进行加密,返回一个字节流
byte[] cipherText = cipher.doFinal(plainText);
cipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
// 用私钥进行解密,返回一个字节流
byte[] newPlainText = cipher.doFinal(cipherText);
System.out.println(new String(newPlainText, “UTF-8”));

Eclipse快捷键 10个最有用的快捷键

Eclipse中10个最有用的快捷键组合

一个Eclipse骨灰级开发者总结了他认为最有用但又不太为人所知的快捷键组合。通过这些组合可以更加容易的浏览源代码,使得整体的开发效率和质量得到提升。    1. ctrl+shift+r:打开资源

这可能是所有快捷键组合中最省时间的了。这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xml。美中不足的是这组快捷键并非在所有视图下都能用。
【转】eclipse快捷键 10个最有用的快捷键

2. ctrl+o:快速outline

如果想要查看当前类的方法或某个特定方法,但又不想把代码拉上拉下,也不想使用查找功能的话,就用ctrl+o吧。它可以列出当前类中的所有方法及属性,你只需输入你想要查询的方法名,点击enter就能够直接跳转至你想去的位置。
【转】eclipse快捷键 10个最有用的快捷键

3. ctrl+e:快速转换编辑器

这组快捷键将帮助你在打开的编辑器之间浏览。使用ctrl+page down或ctrl+page up可以浏览前后的选项卡,但是在很多文件打开的状态下,ctrl+e会更加有效率。
eclipse快捷键 10个最有用的快捷键

4. ctrl+2,L:为本地变量赋值

开发过程中,我常常先编写方法,如Calendar.getInstance(),然后通过ctrl+2快捷键将方法的计算结果赋值于一个本地变量之上。 这样我节省了输入类名,变量名以及导入声明的时间。Ctrl+F的效果类似,不过效果是把方法的计算结果赋值于类中的域。

    5. alt+shift+r:重命名

重命名属性及方法在几年前还是个很麻烦的事,需要大量使用搜索及替换,以至于代码变得零零散散的。今天的Java IDE提供源码处理功能,Eclipse也是一样。现在,变量和方法的重命名变得十分简单,你会习惯于在每次出现更好替代名称的时候都做一次重命名。要使 用这个功能,将鼠标移动至属性名或方法名上,按下alt+shift+r,输入新名称并点击回车。就此完成。如果你重命名的是类中的一个属性,你可以点击alt+shift+r两次,这会呼叫出源码处理对话框,可以实现get及set方法的自动重命名。

    6. alt+shift+l以及alt+shift+m:提取本地变量及方法

源码处理还包括从大块的代码中提取变量和方法的功能。比如,要从一个string创建一个常量,那么就选定文本并按下alt+shift+l即可。如果同 一个string在同一类中的别处出现,它会被自动替换。方法提取也是个非常方便的功能。将大方法分解成较小的、充分定义的方法会极大的减少复杂度,并提 升代码的可测试性。

    7. shift+enter及ctrl+shift+enter

Shift+enter在当前行之下创建一个空白行,与光标是否在行末无关。Ctrl+shift+enter则在当前行之前插入空白行。

    8. Alt+方向键

这也是个节省时间的法宝。这个组合将当前行的内容往上或下移动。在try/catch部分,这个快捷方式尤其好使。

    9. ctrl+m

大显示屏幕能够提高工作效率是大家都知道的。Ctrl+m是编辑器窗口最大化的快捷键。

    10. ctrl+.及ctrl+1:下一个错误及快速修改

ctrl+.将光标移动至当前文件中的下一个报错处或警告处。这组快捷键我一般与ctrl+1一并使用,即修改建议的快捷键。新版Eclipse的修改建 议做的很不错,可以帮你解决很多问题,如方法中的缺失参数,throw/catch exception,未执行的方法等等。
eclipse快捷键 10个最有用的快捷键

更多快捷键组合可在Eclipse按下ctrl+shift+L查看。

让我们按照使用频率来看看我最爱用的一些热键组合。(注:以下内容在Eclipse3.02及一上版本通过测试)

1. Control-Shift-T: 打开类型(Open type)。如果你不是有意磨洋工,还是忘记通过源码树(source tree)打开的方式吧。用eclipse很容易打开接口的实现类的,按ctrl+t会列出接口的实现类列表

2. Control-Shift-R: 打开资源(不只是用来寻找Java文件)。小提示:利用Navigator视图的黄色双向箭头按钮让你的编辑窗口和导航器相关联。这会让你打开的文件对应显示在导航器的层级结构中,这样便于组织信息。如果这影响了速度,就关掉它。

3. F3: 打开申明(Open declaration)。或者,利用Declaration Tab(在Java视图模式下,选择Windows –> Show View — > Declaration)。当你选中代码中的一个方法,然后按这个按键,它会把整个方法在申明方框里显示出来。

4. Alt-left arrow: 在导航历史记录(Navigation History)中后退。就像Web浏览器的后退按钮一样,在利用F3跳转之后,特别有用。(用来返回原先编译的地方)

5. Alt-right arrow: 导航历史记录中向前。

6. Control-Q: 回到最后一次编辑的地方。这个快捷键也是当你在代码中跳转后用的。特别是当你钻的过深,忘记你最初在做什么的时候。

7. Control-Shift-G: 在workspace中搜索引用(reference)这 是重构的前提。对于方法,这个热键的作用和F3恰好相反。它使你在方法的栈中,向上找出一个方法的所有调用者。一个与此相关的功能是开启“标记”功能 (occurrence marking) 。选择Windows->Preferences->Java-> Editor-> Mark Occurrences,勾选选项。这时,当你单击一个元素的时候,代码中所有该元素存在的地方都会被高亮显示。我个人只使用“标记本地变量”(Mark Local Variables)。注意:太多的高亮显示会拖慢Eclipse。

8. Control-Shift-F: 根据代码风格设定重新格式化代码。我 们的团队有统一的代码格式,我们把它放在我们的wiki上。要这么做,我们打开Eclipse,选择Window Style,然后设置Code Formatter,Code Style和Organize Imports。利用导出(Export)功能来生成配置文件。我们把这些配置文件放在wiki上,然后团队里的每个人都导入到自己的Eclipse中。

9. Control-O: 快速概要(quick outline)。通过这个快捷键,你可以迅速的跳到一个方法或者属性,只需要输入名字的头几个字母。

10. Control-/: 对一行注释或取消注释。对于多行也同样适用。

11. Control-Alt-down arrow: 复制高亮显示的一行或多行。

12. Alt-down arrow: 将一行或多行向下移动。Alt-up arrow会向上移动。

其他的热键在菜单里有。你可以通过按下Control-Shift-L(从3.1版本开始), 看到所有快捷键的列表。按下Control-Shift-L两次,会显示热键对话框(Keys Preferences dialog),你可以在这里自己设置热键。我欢迎你在Talkback部分发表你的Eclipse提示。

其他的Eclipse窍门

我总结了几个相关的小窍门:

锁定命令行窗口:在命令行视图中(Window ->Show View ->Other ->Basic ->Console),试试看用滚动锁定按钮来锁定控制台输出不要滚屏。

使用Ant视图: 在我的Java或Debug模式下,我喜欢显示出Ant视图,这样我就可以迅速的运行Ant任务。通过Window Ant可以找到该视图。把Ant视图放在屏幕的一角, 通过“添加编译文件(Addà Other à Show View à Buildfiles)”按钮来添加build.xml文件。在3.1版本中,甚至支持Ant调试脚本语言。

自动遍历一个集合:for + Control-Space: 如果你还不知道,那么你应该记住Control-Space是自动完成功能。在Eclipse中,你还可以自动完成结构。在一个数组或集合范围内,试试看 输入“for”然后按下Control-Space键。Eclipse会问你你想要遍历哪一个集合然后自动完成循环代码。

使用分级布局: 在包浏览视图(Package Explorer view)中默认的布局(扁平式)方式让我困惑,它把包的全名显示在导航树(navigation tree)中。我更喜欢我源码的包和文件系统视图,在Eclipse中叫做分级布局(Hierarchical Layout)。要切换到这种模式,点击包浏览视图中向下的按钮,选择布局(Layout),然后选择分级(Hierarchial)。

一次显示多个文件:你可以一次浏览多个文件。把不在激活状态的编辑窗口拖到激活窗口的底部或侧边的滚动条上,就可以打开该编辑窗口。这是我能描述该窍门的最好方式了。

同时打开两个Eclipse: 要将改动从一个CVS分支上合并到另外一个上,我喜欢通过同时打开两个工作目录(Workspace)不同Eclipse来实现。这样我可以通过比较 CVS上的最新版本看到所有的变化(右键单击工程,然后选择Compare Lastest from HEAD)然后把每一个变化都合并到另外一个CVS分支上。启动多个Eclipse的最简单的方法是利用Eclipseàwith Launcher。

Implementors插件:安装一个能够跳到一个接口的实现的插件。如果你是个dependency injection 粉丝,或者正在基于编写优良的接口工作,那么你需要一个这样的插件来加速代码导航。 你可以在SourceForge找到这个插件。

 

 

Ctrl+Alt+H

如果你想知道一个类的方法到底被那些其他的类调用,那么请选中这个方法名,然后按“Ctrl+Alt+H”,

Eclipse就会显示出这个方法被哪些方法调用,最终产生一个调用关系树。
1. Ctrl+左键

 

 

 

 

 

 

 
这个是大多数人经常用到的,用来查看变量、方法、类的定义

2. Ctrl+O

查看一个类的纲要,列出其方法和成员变量。提示:再多按一次Ctrl+O,可以列出该类继承的方法和变量。

助记:”O”—>”Outline”—>”纲要”

3. Ctrl+T

查看一个类的继承关系树,是自顶向下的,再多按一次Ctrl+T, 会换成自底向上的显示结构。

提示:选中一个方法名,按Ctrl+T,可以查看到有这个同名方法的父类、子类、接口。

助记:”T”——->”Tree”—–>”层次树”

4.Alt+左右方向键

我们经常会遇到看代码时Ctrl+左键,层层跟踪,然后迷失在代码中的情况,这时只需要按“Alt+左方向键

”就可以退回到上次阅读的位置,同理,按“Alt+右方向键”会前进到刚才退回的阅读位置,就像浏览器的

前进和后退按钮一样。

 

 

 

 

 

 

 

 

 

 

导入包:Ctrl+Shift+O
编辑
作用域 功能 快捷键
全局 查找并替换 Ctrl+F
文本编辑器 查找上一个 Ctrl+Shift+K
文本编辑器 查找下一个 Ctrl+K
全局 撤销 Ctrl+Z
全局 复制 Ctrl+C
全局 恢复上一个选择 Alt+Shift+↓
全局 剪切 Ctrl+X
全局 快速修正 Ctrl1+1
全局 内容辅助 Alt+/
全局 全部选中 Ctrl+A
全局 删除 Delete
全局 上下文信息 Alt+?
Alt+Shift+?
Ctrl+Shift+Space
Java编辑器 显示工具提示描述 F2
Java编辑器 选择封装元素 Alt+Shift+↑
Java编辑器 选择上一个元素 Alt+Shift+←
Java编辑器 选择下一个元素 Alt+Shift+→
文本编辑器 增量查找 Ctrl+J
文本编辑器 增量逆向查找 Ctrl+Shift+J
全局 粘贴 Ctrl+V
全局 重做 Ctrl+Y
查看
作用域 功能 快捷键
全局 放大 Ctrl+=
全局 缩小 Ctrl+-
窗口
作用域 功能 快捷键
全局 激活编辑器 F12
全局 切换编辑器 Ctrl+Shift+W
全局 上一个编辑器 Ctrl+Shift+F6
全局 上一个视图 Ctrl+Shift+F7
全局 上一个透视图 Ctrl+Shift+F8
全局 下一个编辑器 Ctrl+F6
全局 下一个视图 Ctrl+F7
全局 下一个透视图 Ctrl+F8
文本编辑器 显示标尺上下文菜单 Ctrl+W
全局 显示视图菜单 Ctrl+F10
全局 显示系统菜单 Alt+-
导航
作用域 功能 快捷键
Java编辑器 打开结构 Ctrl+F3
全局 打开类型 Ctrl+Shift+T
全局 打开类型层次结构 F4
全局 打开声明 F3
全局 打开外部javadoc Shift+F2
全局 打开资源 Ctrl+Shift+R
全局 后退历史记录 Alt+←
全局 前进历史记录 Alt+→
全局 上一个 Ctrl+,
全局 下一个 Ctrl+.
Java编辑器 显示大纲 Ctrl+O
全局 在层次结构中打开类型 Ctrl+Shift+H
全局 转至匹配的括号 Ctrl+Shift+P
全局 转至上一个编辑位置 Ctrl+Q
Java编辑器 转至上一个成员 Ctrl+Shift+↑
Java编辑器 转至下一个成员 Ctrl+Shift+↓
文本编辑器 转至行 Ctrl+L
搜索
作用域 功能 快捷键
全局 出现在文件中 Ctrl+Shift+U
全局 打开搜索对话框 Ctrl+H
全局 工作区中的声明 Ctrl+G
全局 工作区中的引用 Ctrl+Shift+G
文本编辑
作用域 功能 快捷键
文本编辑器 改写切换 Insert
文本编辑器 上滚行 Ctrl+↑
文本编辑器 下滚行 Ctrl+↓
文件
作用域 功能 快捷键
全局 保存 Ctrl+X
Ctrl+S
全局 打印 Ctrl+P
全局 关闭 Ctrl+F4
全局 全部保存 Ctrl+Shift+S
全局 全部关闭 Ctrl+Shift+F4
全局 属性 Alt+Enter
全局 新建 Ctrl+N
项目
作用域 功能 快捷键
全局 全部构建 Ctrl+B
源代码
作用域 功能 快捷键
Java编辑器 格式化 Ctrl+Shift+F
Java编辑器 取消注释 Ctrl+/
Java编辑器 注释 Ctrl+/
Java编辑器 添加单个import Ctrl+Shift+M
Java编辑器 组织多个import Ctrl+Shift+O
Java编辑器 使用try/catch块来包围 未设置,太常用了,所以在这里列出,建议自己设置。
也可以使用Ctrl+1自动修正。
调试/运行
作用域 功能 快捷键
全局 单步返回 F7
全局 单步跳过 F6
全局 单步跳入 F5
全局 单步跳入选择 Ctrl+F5
全局 调试上次启动 F11
全局 继续 F8
全局 使用过滤器单步执行 Shift+F5
全局 添加/去除断点 Ctrl+Shift+B
全局 显示 Ctrl+D
全局 运行上次启动 Ctrl+F11
全局 运行至行 Ctrl+R
全局 执行 Ctrl+U
重构
作用域 功能 快捷键
全局 撤销重构 Alt+Shift+Z
全局 抽取方法 Alt+Shift+M
全局 抽取局部变量 Alt+Shift+L
全局 内联 Alt+Shift+I
全局 移动 Alt+Shift+V
全局 重命名 Alt+Shift+R
全局 重做 Alt+Shift+Y

 

 

 

 

 

 

 

 

(1)Ctrl+M切换窗口的大小
(2)Ctrl+Q跳到最后一次的编辑处
(3)F2当鼠标放在一个标记处出现Tooltip时候按F2则把鼠标移开时Tooltip还会显示即Show Tooltip

Description。
F3跳到声明或定义的地方。
F5单步调试进入函数内部。
F6单步调试不进入函数内部,如果装了金山词霸2006则要把“取词开关”的快捷键改成其他的。
F7由函数内部返回到调用处。
F8一直执行到下一个断点。
(4)Ctrl+Pg~对于XML文件是切换代码和图示窗口
(5)Ctrl+Alt+I看Java文件中变量的相关信息
(6)Ctrl+PgUp对于代码窗口是打开“Show List”下拉框,在此下拉框里显示有最近曾打开的文件
(7)Ctrl+/ 在代码窗口中是这种//~注释。
Ctrl+Shift+/ 在代码窗口中是这种/*~*/注释,在JSP文件窗口中是〈!–~–〉。
(8)Alt+Shift+O(或点击工具栏中的Toggle Mark Occurrences按钮) 当点击某个标记时可使本页面中其他

地方的此标记黄色凸显,并且窗口的右边框会出现白色的方块,点击此方块会跳到此标记处。
(9)右击窗口的左边框即加断点的地方选Show Line Numbers可以加行号。
(10)Ctrl+I格式化激活的元素Format Active Elements。
Ctrl+Shift+F格式化文件Format Document。
(11)Ctrl+S保存当前文件。
Ctrl+Shift+S保存所有未保存的文件。
(12)Ctrl+Shift+M(先把光标放在需导入包的类名上) 作用是加Import语句。
Ctrl+Shift+O作用是缺少的Import语句被加入,多余的Import语句被删除。
(13)Ctrl+Space提示键入内容即Content Assist,此时要将输入法中Chinese(Simplified)IME-

Ime/Nonlme Toggle的快捷键(用于切换英文和其他文字)改成其他的。
Ctrl+Shift+Space提示信息即Context Information。
(14)双击窗口的左边框可以加断点。
(15)Ctrl+D删除当前行。

Eclipse快捷键大全
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)
Ctrl+D: 删除当前行
Ctrl+Alt+↓ 复制当前行到下一行(复制增加)
Ctrl+Alt+↑ 复制当前行到上一行(复制增加)

Alt+↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了)
Alt+↑ 当前行和上面一行交互位置(同上)
Alt+← 前一个编辑的页面
Alt+→ 下一个编辑的页面(当然是针对上面那条来说了)

Alt+Enter 显示当前选择资源(工程,or 文件 or文件)的属性

Shift+Enter 在当前行的下一行插入空行(这时鼠标可以在当前行的任一位置,不一定是最后)
Shift+Ctrl+Enter 在当前行插入空行(原理同上条)

Ctrl+Q 定位到最后编辑的地方
Ctrl+L 定位在某行 (对于程序超过100的人就有福音了)
Ctrl+M 最大化当前的Edit或View (再按则反之)
Ctrl+/ 注释当前行,再按则取消注释
Ctrl+O 快速显示 OutLine
Ctrl+T 快速显示当前类的继承结构
Ctrl+W 关闭当前Editer
Ctrl+K 参照选中的Word快速定位到下一个
Ctrl+E 快速显示当前Editer的下拉列表(如果当前页面没有显示的用黑体表示)

Ctrl+/(小键盘) 折叠当前类中的所有代码

Ctrl+×(小键盘) 展开当前类中的所有代码

Ctrl+Space 代码助手完成一些代码的插入(但一般和输入法有冲突,可以修改输入法的热键,也可以暂用

Alt+/来代替)

Ctrl+Shift+E 显示管理当前打开的所有的View的管理器(可以选择关闭,激活等操作)

Ctrl+J 正向增量查找(按下Ctrl+J后,你所输入的每个字母编辑器都提供快速匹配定位到某个单词,如果没有

,则在stutes line中显示没有找到了,查一个单词时,特别实用,这个功能Idea两年前就有了)

Ctrl+Shift+J 反向增量查找(和上条相同,只不过是从后往前查)

Ctrl+Shift+F4 关闭所有打开的Editer

Ctrl+Shift+X 把当前选中的文本全部变味小写

Ctrl+Shift+Y 把当前选中的文本全部变为小写

Ctrl+Shift+F 格式化当前代码

Ctrl+Shift+P 定位到对于的匹配符(譬如{}) (从前面定位后面时,光标要在匹配符里面,后面到前面,则反之

)

下面的快捷键是重构里面常用的,本人就自己喜欢且常用的整理一下(注:一般重构的快捷键都是Alt+Shift开

头的了)

Alt+Shift+R 重命名 (是我自己最爱用的一个了,尤其是变量和类的Rename,比手工方法能节省很多劳动力)

Alt+Shift+M 抽取方法 (这是重构里面最常用的方法之一了,尤其是对一大堆泥团代码有用)

Alt+Shift+C 修改函数结构(比较实用,有N个函数调用了这个方法,修改一次搞定)

Alt+Shift+L 抽取本地变量( 可以直接把一些魔法数字和字符串抽取成一个变量,尤其是多处调用的时候)

Alt+Shift+F 把Class中的local变量变为field变量 (比较实用的功能)

Alt+Shift+I 合并变量(可能这样说有点不妥Inline)
Alt+Shift+V 移动函数和变量(不怎么常用)
Alt+Shift+Z 重构的后悔药(Undo)

链接http://hi.baidu.com/lzycsd/blog/item/dcce5989a3f559bb0f2444cb.html

Java的反射机制


1.反射不受到public,private,protected等的限制,
可以随意创建,修改,读取private(等)类的private(等)函数或者成员变量
2.
Class clz = Class.forName("类名")

Method mtd = clz.getMethod("函数名",new Class[]{参数类型列表})
这种方法只能获取到clz类中public的函数,private的函数无法获取到

Method mtd = clz.getDeclaredMethod("函数名",new Class[]{参数类型列表})
这种方法能够获取到clz类的所有声明的函数,无论是public的,private的还是protected的

Field,同样有clz.getField和clz.getDeclaredField之分(与Method同理)

mtd.invoke(obj,new Object[]{参数列表})
如果是一个实例函数的调用(非static的函数), 则obj应该是该类的实例
如果调用的是static函数,obj = null即可

常用的写法:

                Class DexFileClz = Class.forName("dalvik.system.DexFile");
		
		Class[] paratype = new Class[1];
		paratype[0] = byte[].class;   //注意 数组的类型 如何表示
				
		Object[] paraobj = new Object[1];
		paraobj[0] = dexContent;//dexContent是byte[]
		
		Method openDexFilemtd = DexFileClz.getDeclaredMethod("openDexFile", paratype);
		openDexFilemtd.setAccessible(true);    //不管是否private,protected,在该程序中都设为可见.
		int retv = (Integer) openDexFilemtd.invoke(null, paraobj);

3.如果反射返回的object是一个数组类型,

例如:
		Object dexElements = RefInvoke.getFieldOjbect("dalvik.system.DexPathList", pthList, "dexElements");

其中dexElements是一个final的protected类, 对当前的程序员来说是不可见的, 所以无法进行强制类型转换. 那么如果想要操作其中的每个
元素就需要使用Array类型:

		int length = Array.getLength(dexElements); //获取数组的长度

		Object ele = Array.get(dexElements, i); //获取数组的第i个元素,i从0开始 (i即数组index)

以上都能明白, Java的反射再无困难

==== === === =天使般的分割线 = = = == = = == = = = = =

以下为反射常用函数集合,若用到反射,下类基本够用!



import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class RefInvoke {
	
	public static  Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules){
		
		try {
			Class obj_class = Class.forName(class_name);
			Method method = obj_class.getMethod(method_name,pareTyple);
			return method.invoke(null, pareVaules);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static  Object invokeMethod(String class_name, String method_name, Object obj ,Class[] pareTyple, Object[] pareVaules){
		
		try {
			Class obj_class = Class.forName(class_name);
			Method method = obj_class.getMethod(method_name,pareTyple);
			return method.invoke(obj, pareVaules);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		}  catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static Object getFieldOjbect(String class_name,Object obj, String filedName){
		try {
			Class obj_class = Class.forName(class_name);
			Field field = obj_class.getDeclaredField(filedName);
			field.setAccessible(true);
			return field.get(obj);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static Object getStaticFieldOjbect(String class_name, String filedName){
		
		try {
			Class obj_class = Class.forName(class_name);
			Field field = obj_class.getDeclaredField(filedName);
			field.setAccessible(true);
			return field.get(null);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}
		return null;
		
	}
	
	public static void setFieldOjbect(String classname, String filedName, Object obj, Object filedVaule){
		try {
			Class obj_class = Class.forName(classname);
			Field field = obj_class.getDeclaredField(filedName);
			field.setAccessible(true);
			field.set(obj, filedVaule);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}	
	}
	
	public static void setStaticOjbect(String class_name, String filedName, Object filedVaule){
		try {
			Class obj_class = Class.forName(class_name);
			Field field = obj_class.getDeclaredField(filedName);
			field.setAccessible(true);
			field.set(null, filedVaule);
		} catch (SecurityException e) {
			
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			
			e.printStackTrace();
		}		
	}


}

ubuntu 13.04 安装 JDK

  具体步骤参详了如下链接:

http://blog.csdn.net/yang_hui1986527/article/details/6677450

  1、到 Sun 的官网下载

http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
  选择 accept license ,然后选择适合自己机型的JDK下载。

  2、解压文件,修改文件名

$ sudo mkdir /usr/lib/jvm
$ sudo tar zxvf jdk-7u21-linux-i586.tar.gz -C /usr/lib/jvm
$ cd /usr/lib/jvm
$ sudo mv jdk1.7.0_21 java
  3、添加环境变量

$ sudo vim ~/.bashrc
  加入如下内容

export JAVA_HOME=/usr/lib/jvm/java
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
  4、配置默认JDK版本

sudo update-alternatives –install /usr/bin/java java /usr/lib/jvm/java/bin/java 300
sudo update-alternatives –install /usr/bin/javac javac /usr/lib/jvm/java/bin/javac 300
sudo update-alternatives –install /usr/bin/jar jar /usr/lib/jvm/java/bin/jar 300
sudo update-alternatives –install /usr/bin/javah javah /usr/lib/jvm/java/bin/javah 300
sudo update-alternatives –install /usr/bin/javap javap /usr/lib/jvm/java/bin/javap 300
  然后执行

sudo update-alternatives –config java
  若是初次安装 JDK, 将提示

There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java/bin/java
无需配置。
  若是非初次安装,将有不同版本的 JDK 选项。

  5、测试

$ java -version
java version “1.7.0_21”
Java(TM) SE Runtime Environment (build 1.7.0_21-b11)
Java HotSpot(TM) Server VM (build 23.21-b01, mixed mode)

jdb调试运行本地jar包

运行命令:

1一个shell中,使用该命令启动jar

java -agentlib:jdwp=transport=dt_socket,server=y,address=8000 -jar jeb.jar

另一个shell中,使用jdb连接该调试线程:

jdb -attach localhost:8000

 

须在启动之前下好断点,以便单步调试.故此需要对jar内的类以及函数有所了解.

可以使用jd-gui或者jad反编译原始jar包,阅读java代码对原始jar稍作了解.

 

———————————————–

要进行调试,你必须将调试JDWP代理加载到应用程序的JVM中。从Java 5.0开始,你可以用-agentlib:jdwp选项来完成加载。5.0以前版本则使用-Xdebug和-Xrunjdwp选项(5.0也支持-Xdebug和-Xrunjdwp选项,不过新的-agentlib:jdwp选项更加好用。因为5.0中的JDWP代理使用JVMTI接口连接VM,而非旧的JVMDI接口)。你应该向-agentlib:jdwp(Java 5.0中)或-Xrunjdwp(Java 5.0以前版本) 参数提供子选项;两组可能的子选项相同。

以下列方式指定子选项:

-agentlib:jdwp=<name1>[=<value1>],<name2>[=<value2>]…

-Xrunjdwp:<name1>[=<value1>],<name2>[=<value2>]…

你可以使用这些选项:

help:打印如何应用它的简单信息,并退出VM。
server:(是”y”或否”n”):如“server=y”,收到一个要依附的调试应用程序;如“server=n”,依附到指定地址的调试应用程序。
address:连接传送地址。如果server=n,尝试依附到这个地址的调试应用程序;如server=y,收到这个地址的连接。
timeout:如果server=y,它以毫秒为单位指定等待调试器依附的时间;如server=n,它以毫秒为单位指定依附到调试器所用的时间。
suspend:如“是”,JVM延缓执行,直到调试器与被调试JVM建立连接。
以下是命令行实例:

-agentlib:jdwp=transport=dt_socket,server=y,address=8000

在端口8000收听一个套接字连接。在主类加载前延缓这个VM(默认suspend=y)。一旦连接上调试应用程序,它发送一个JDWP命令恢复VM。

-agentlib:jdwp=transport=dt_shmem,server=y,suspend=n

选择一个有效的共享内存传输地址并将它打印出来。在那个地址收听一个共享内存连接。在调试应用程序依附之前,允许VM开始执行。

-agentlib:jdwp=transport=dt_socket,address=myhost:8000

通过myhost主机端口8000的套接字依附到一个运行的调试应用程序。在主类加载前延缓这个VM。

————————————————

—————————————————–

由于直接使用JDB调试时,浏览源代码时很不方便,如果机器上安装了emacs,可以直接在emacs里启动JDB,获取跟eclipse相近的源代码级别的调试体验。

 

在emacs里运行JDB的方法:

1.在emacs里按下ALT+X键,在提示符后面输入JDB,敲击回车。
2.接着再输入JDB的启动参数。
3.按下CTRL + X,2键,将emacs分屏。
4.再按CTRL + X, B键,将其中一个屏幕显示源代码。
5.按CTRL + X, O键,再两个屏幕间切换。
6.在JDB的那个窗口里输入正常的调试命令。
———————————————————————-

 

参考:

http://tech.it168.com/j/2006-12-22/200612221226341_1.shtml

http://wenku.baidu.com/link?url=vWrcQVtSL97AlqPzkTGVdUoVJaPR_WOiu9Ok_5dibE72lygVMTe9iI2aNLy5gSs8oEe_qd0lBmGzHSIrqB5IQPqHzdPr8iTEAWog17Owa1q

用 dalvikvm 执行一个运行于命令行的 Hello World

Windows 操作系统也有五花八门的应用 ,可是想当年学习编程语言的第一个程序,却是在 Turbo C  蓝漆漆的界面里笨拙地敲一个 Hello World 程序 ,然后又在黑漆漆的命令行里打印出的一行输出结果 ,“Hello World”。

Android 上也能实现类似的效果 ,可以使用 dalvikvm 执行一个运行于命令行的 Hello World 。

简要的过程如下:
写代码 Hello.java
编译成 Android Dalvik Virtual Machine 的可执行文件 Hello.dex
使用 ADB 运行测试
内容主要参考 Android 4.4 源码里 dalvik / docs / hello-world.html 文件 。

1. 本文的测试环境
Ubuntu 12.04 64-bit
JDK 1.6
安装 Android SDK,并安装 Android SDK build_tools , 最新版是 19.0.1
具有 Root 权限的 ADB shell

2. 创建 java 源文件 ,内容如下

代码:
public class Hello
{
  public static void main(String[] argc)
  {
    System.out.println("Hello, Android!\n");
  }
}

3.编译
(1)编译成 java class 文件
执行命令 : javac Hello.java
编译完成后 ,目录下生成 Hello.class 文件 。可以使用命令 java Hello 来测试下 ,会输出代码中的 “ Hello, Android!” 的字符串 。
(2) 编译成 dex 文件
编译工具在 Android SDK 的路径如下 ,其中 19.0.1 是Android SDK build_tools  的版本 ,请按照在本地安装的  build_tools 版本来 。建议该路径加载到 PATH 路径下 ,否则引用 dx 工具时需要使用绝对路径 。
./build-tools/19.0.1/dx
执行命令 : dx –dex –output=Hello.dex Hello.class
编译正常会生成 Hello.dex 文件 。

4. 使用 ADB 运行测试
测试命令和输出结果如下 :
$ adb root
$ adb push Hello.dex  /sdcard/
$ adb shell
root@maguro:/ # dalvikvm -cp /sdcard/Hello.dex Hello
Hello, Android!

说明 :
(1)测试环境使用真机和 Android 虚拟机都可以的 。核心的命令是
dalvikvm -cp /sdcard/Hello.dex Hello
-cp 是 class path 的缩写 ,后面的 Hello 是要运行的 Class 的名称 。网上有描述说输入 dalvikvm  –help 可以看到  dalvikvm 的帮助文档 ,但是在 Android4.4 的官方模拟器和自己的手机上测试都提示找不到 Class 路径 ,在Android 老的版本 ( 4.3 ) 上测试还是有输出的 。
(2)因为命令在执行时 , dalvikvm 会在 /data/dalvik-cache/  目录下创建 .dex 文件 ,因此要求 ADB 的执行 Shell 对目录 /data/dalvik-cache/  有读、写和执行的权限 ,否则无法达到预期效果 。

原链接: http://bbs.pediy.com/showthread.php?t=184592

JAVA不定参数探秘

JAVA中可以使用不定参数,

例如 public void test(String …args){…} 这里test方法可以传入参数的情况是:

1.不使用参数,如test()

2.使用一个或多个参数,如test(“1”); test(“1″,”2”);

3.使用数组 test(new String[]{“1″,”2”});

在test方法内部,我们可以像使用数组的访问方式一样来访问参数args.如:args[i] 这样就有一个好处,在参数输入不定的情况下,使用这个方法非常简单。非常易于使用。

有几点需要注意的就是  

  我们见到的是不定参数,其实编译器编译之后它会将这个test(String …args){…} 编译成为数组调用的方式test(String[] args){} ,这个过程是编译中就完成了的,我们程序编写过程中看不到这个实际的转换过程。  而我们调用这个test方法时,编译器同样会把参数转换成new String[]{“”}的形式调用,所以,本质上来讲,就是一个以数组为参数的调用方法,我们看不到而已,具体详细情况可以反编译class类就可以明了。

如果同时同一个类中还有一个test方法,例如test(),或者test(String args) ,我们采用 test(“1”)的方式调用,我们就可以知道了,因为有这个方法存在,所以编译器就会优先使用这个 test(String args)    方法,而不会使用不定参数的方法,这个原因很明确,因为不定参数本质上是一个数组为参数的方式。所以,如果你定义了一个不定参数的test方法,如果你再定义一个test(String[] args)的以数组为参数的方法,编译器就会提示你方法定义重复。道理就在这里。

  希望以上的解释能够帮助到大家。

原链接: http://www.cnblogs.com/lovingprince/archive/2008/05/20/2166386.html

init与clinit的区别

今天在看深入Java虚拟机的class文件结构时,看到了这么一句话,

可能出现在class文件中的两种编译器产生的方法是:实例初始化方法(名为<init>)和类与接口初始化方法(名为<clinit>)。

 

这两种方法有什么区别呢?

首先:这两个方法一个是虚拟机在装载一个类初始化的时候调用的(clinit)。另一个是在类实例化时调用的(init)

 

首先说说类的初始化:

在Java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。一个类变量初始化语句是

变量声明后的等号和表达式:

Java代码  收藏代码
  1. class Example {
  2.        static int size = 3 * (int) (Math.random() * 5.0);
  3. }

 

静态初始化语句是一个以static开头的语句块:

Java代码  收藏代码
  1. class Example{
  2.      static int size;
  3.      static {
  4.            size = 3 * (int) (Math.random() * 5.0);
  5.      }
  6. }

所有的类变量初始化语句和类型的静态初始化语句都被Java编译器收集到了一起,放在一个特殊的方法中。这个方法就是<clinit>

 

我们在来看看<init>这个方法:

<init>方法是在一个类进行对象实例化时调用的。实例化一个类有四种途径:调用new操作符;调用Class或java.lang.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;通过java.io.ObjectInputStream类的getObject()方法反序列化。

 

Java编译器会为它的每一个类都至少生成一个实例初始化方法。在Class文件中,被称为”<init>”

 

现在知道了吧, 一个是用于初始化静态的类变量, 一个是初始化实例变量!