君不见长松卧壑困风霜,时来屹立扶明堂。这篇文章主要讲述Java ASM系列:(051)opcode: constant相关的知识,希望能为你提供帮助。
本文属于Java ASM系列二:OPCODE当中的一篇。
对于《java ASM系列二:OPCODE》有配套的视频讲解,可以点击这里和这里进行查看;同时,也可以点击这里查看源码资料。
1. 概览从Instruction的角度来说,与constant相关的opcode有20个,内容如下:
opcode | mnemonic symbol | opcode | mnemonic symbol | opcode | mnemonic symbol | opcode | mnemonic symbol |
---|---|---|---|---|---|---|---|
1 | aconst_null | 6 | iconst_3 | 11 | fconst_0 | 16 | bipush |
2 | iconst_m1 | 7 | iconst_4 | 12 | fconst_1 | 17 | sipush |
3 | iconst_0 | 8 | iconst_5 | 13 | fconst_2 | 18 | ldc |
4 | iconst_1 | 9 | lconst_0 | 14 | dconst_0 | 19 | ldc_w |
5 | iconst_2 | 10 | lconst_1 | 15 | dconst_1 | 20 | ldc2_w |
MethodVisitor.visitXxxInsn()
方法对应关系如下:MethodVisitor.visitInsn()
:aconst_null
,iconst_& lt; i& gt;
,lconst_& lt; l& gt;
,fconst_& lt; f& gt;
,dconst_& lt; d& gt;
MethodVisitor.visitIntInsn()
:bipush
,sipush
MethodVisitor.visitLdcInsn()
:ldc
,ldc_w
,ldc2_w
iconst_&
lt;
i&
gt;
: -1~5从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
int int_m1 = -1;
int int_0 = 0;
int int_1 = 1;
int int_2 = 2;
int int_3 = 3;
int int_4 = 4;
int int_5 = 5;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_m1
1: istore_1
2: iconst_0
3: istore_2
4: iconst_1
5: istore_3
6: iconst_2
7: istore4
9: iconst_3
10: istore5
12: iconst_4
13: istore6
15: iconst_5
16: istore7
18: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_M1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 4);
methodVisitor.visitInsn(ICONST_3);
methodVisitor.visitVarInsn(ISTORE, 5);
methodVisitor.visitInsn(ICONST_4);
methodVisitor.visitVarInsn(ISTORE, 6);
methodVisitor.visitInsn(ICONST_5);
methodVisitor.visitVarInsn(ISTORE, 7);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 8);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: iconst_m1// {this} | {int}
0001: istore_1// {this, int} | {}
0002: iconst_0// {this, int} | {int}
0003: istore_2// {this, int, int} | {}
0004: iconst_1// {this, int, int} | {int}
0005: istore_3// {this, int, int, int} | {}
0006: iconst_2// {this, int, int, int} | {int}
0007: istore4// {this, int, int, int, int} | {}
0009: iconst_3// {this, int, int, int, int} | {int}
0010: istore5// {this, int, int, int, int, int} | {}
0012: iconst_4// {this, int, int, int, int, int} | {int}
0013: istore6// {this, int, int, int, int, int, int} | {}
0015: iconst_5// {this, int, int, int, int, int, int} | {int}
0016: istore7// {this, int, int, int, int, int, int, int} | {}
0018: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., <
i>
Push the
int
constant &
lt;
i&
gt;
(-1, 0, 1, 2, 3, 4 or 5) onto the operand stack.2.2. bipush: -128~127
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
int int_m128 = -128;
int int_127 = 127;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: bipush-128
2: istore_1
3: bipush127
5: istore_2
6: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitIntInsn(BIPUSH, -128);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitIntInsn(BIPUSH, 127);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 3);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: bipush-128// {this} | {int}
0002: istore_1// {this, int} | {}
0003: bipush127// {this, int} | {int}
0005: istore_2// {this, int, int} | {}
0006: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
The immediate byte is sign-extended to an
int
value. That value
is pushed onto the operand stack.Format
bipush
byte
2.3. sipush: -32768~32767
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
int int_m32768 = -32768;
int int_32767 = 32767;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: sipush-32768
3: istore_1
4: sipush32767
7: istore_2
8: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitIntInsn(SIPUSH, -32768);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitIntInsn(SIPUSH, 32767);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 3);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: sipush-32768// {this} | {int}
0003: istore_1// {this, int} | {}
0004: sipush32767// {this, int} | {int}
0007: istore_2// {this, int, int} | {}
0008: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
sipush
byte1
byte2
The immediate unsigned
byte1
and byte2
values are assembled into an intermediate short
, where the value
of the short
is (byte1 &
lt;
&
lt;
8) | byte2
. The intermediate value
is then sign-extended to an int
value. That value
is pushed onto the operand stack.2.4. ldc: MIN~MAX
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
int int_min = Integer.MIN_VALUE;
int int_max = Integer.MAX_VALUE;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc#3// int -2147483648
2: istore_1
3: ldc#4// int 2147483647
5: istore_2
6: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(new Integer(-2147483648));
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitLdcInsn(new Integer(2147483647));
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 3);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc#3// {this} | {int}
0002: istore_1// {this, int} | {}
0003: ldc#4// {this, int} | {int}
0005: istore_2// {this, int, int} | {}
0006: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
ldc
index
The
index
is an unsigned byte that must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at index
either must be a run-time constant of type int
or float
, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle.3. long 3.1.
lconst_&
lt;
l&
gt;
: 0~1从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
long long_0 = 0;
long long_1 = 1;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: lconst_0
1: lstore_1
2: lconst_1
3: lstore_3
4: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(LCONST_0);
methodVisitor.visitVarInsn(LSTORE, 1);
methodVisitor.visitInsn(LCONST_1);
methodVisitor.visitVarInsn(LSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: lconst_0// {this} | {long, top}
0001: lstore_1// {this, long, top} | {}
0002: lconst_1// {this, long, top} | {long, top}
0003: lstore_3// {this, long, top, long, top} | {}
0004: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., <
l>
Push the
long
constant &
lt;
l&
gt;
(0 or 1) onto the operand stack.3.2. ldc2_w: MIN~MAX
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
long long_min = Long.MIN_VALUE;
long long_max = Long.MAX_VALUE;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc2_w#3// long -9223372036854775808l
3: lstore_1
4: ldc2_w#5// long 9223372036854775807l
7: lstore_3
8: return
}
【Java ASM系列((051)opcode: constant)】从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(new Long(-9223372036854775808L));
methodVisitor.visitVarInsn(LSTORE, 1);
methodVisitor.visitLdcInsn(new Long(9223372036854775807L));
methodVisitor.visitVarInsn(LSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc2_w#3// {this} | {long, top}
0003: lstore_1// {this, long, top} | {}
0004: ldc2_w#5// {this, long, top} | {long, top}
0007: lstore_3// {this, long, top, long, top} | {}
0008: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
The numeric
value
of that run-time constant is pushed onto the operand stack as a long
or double
, respectively.Format
ldc2_w
indexbyte1
indexbyte2
The unsigned
indexbyte1
and indexbyte2
are assembled into an unsigned 16-bit index
into the run-time constant pool of the current class, where the value of the index
is calculated as (indexbyte1 &
lt;
&
lt;
8) | indexbyte2
. The index
must be a valid index into the run-time constant pool of the current class.4. float 4.1.
fconst_&
lt;
f&
gt;
: 0~2从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
float float_0 = 0;
float float_1 = 1;
float float_2 = 2;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: fconst_0
1: fstore_1
2: fconst_1
3: fstore_2
4: fconst_2
5: fstore_3
6: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(FCONST_0);
methodVisitor.visitVarInsn(FSTORE, 1);
methodVisitor.visitInsn(FCONST_1);
methodVisitor.visitVarInsn(FSTORE, 2);
methodVisitor.visitInsn(FCONST_2);
methodVisitor.visitVarInsn(FSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 4);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: fconst_0// {this} | {float}
0001: fstore_1// {this, float} | {}
0002: fconst_1// {this, float} | {float}
0003: fstore_2// {this, float, float} | {}
0004: fconst_2// {this, float, float} | {float}
0005: fstore_3// {this, float, float, float} | {}
0006: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., <
f>
Push the
float
constant &
lt;
f&
gt;
(0.0, 1.0, or 2.0) onto the operand stack.4.2. ldc: MIN~MAX
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
float float_min = Float.MIN_VALUE;
float float_max = Float.MAX_VALUE;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc#3// float 1.4E-45f
2: fstore_1
3: ldc#4// float 3.4028235E38f
5: fstore_2
6: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(new Float("1.4E-45"));
methodVisitor.visitVarInsn(FSTORE, 1);
methodVisitor.visitLdcInsn(new Float("3.4028235E38"));
methodVisitor.visitVarInsn(FSTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 3);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc#3// {this} | {float}
0002: fstore_1// {this, float} | {}
0003: ldc#4// {this, float} | {float}
0005: fstore_2// {this, float, float} | {}
0006: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
ldc
index
The
index
is an unsigned byte that must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at index
either must be a run-time constant of type int
or float
, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle.5. double 5.1.
dconst_&
lt;
d&
gt;
: 0~1从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
double double_0 = 0;
double double_1 = 1;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: dconst_0
1: dstore_1
2: dconst_1
3: dstore_3
4: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(DCONST_0);
methodVisitor.visitVarInsn(DSTORE, 1);
methodVisitor.visitInsn(DCONST_1);
methodVisitor.visitVarInsn(DSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: dconst_0// {this} | {double, top}
0001: dstore_1// {this, double, top} | {}
0002: dconst_1// {this, double, top} | {double, top}
0003: dstore_3// {this, double, top, double, top} | {}
0004: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., <
d>
Push the
double
constant &
lt;
d&
gt;
(0.0 or 1.0) onto the operand stack.5.2. ldc2_w: MIN~MAX
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
double double_min = Double.MIN_VALUE;
double double_max = Double.MAX_VALUE;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc2_w#3// double 4.9E-324d
3: dstore_1
4: ldc2_w#5// double 1.7976931348623157E308d
7: dstore_3
8: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(new Double("4.9E-324"));
methodVisitor.visitVarInsn(DSTORE, 1);
methodVisitor.visitLdcInsn(new Double("1.7976931348623157E308"));
methodVisitor.visitVarInsn(DSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc2_w#3// {this} | {double, top}
0003: dstore_1// {this, double, top} | {}
0004: ldc2_w#5// {this, double, top} | {double, top}
0007: dstore_3// {this, double, top, double, top} | {}
0008: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
The numeric
value
of that run-time constant is pushed onto the operand stack as a long
or double
, respectively.6. reference type 6.1. null: aconst_null
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
Object obj_null = null;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: aconst_null
1: astore_1
2: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ACONST_NULL);
methodVisitor.visitVarInsn(ASTORE, 1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 2);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: aconst_null// {this} | {null}
0001: astore_1// {this, null} | {}
0002: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., null
Push the
null
object reference onto the operand stack.6.2. String: ldc
从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
String str = "GoodChild";
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc#2// String GoodChild
2: astore_1
3: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn("GoodChild");
methodVisitor.visitVarInsn(ASTORE, 1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 2);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc#2// {this} | {String}
0002: astore_1// {this, String} | {}
0003: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
ldc
index
The
index
is an unsigned byte that must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at index
either must be a run-time constant of type int
or float
, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle.6.3.
Class&
lt;
?&
gt;
: ldc从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
public void test() {
Class<
?>
clazz = HelloWorld.class;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc#2// class sample/HelloWorld
2: astore_1
3: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn(Type.getType("Lsample/HelloWorld;
"));
methodVisitor.visitVarInsn(ASTORE, 1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 2);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc#2// {this} | {Class}
0002: astore_1// {this, Class} | {}
0003: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
ldc
index
The
index
is an unsigned byte that must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at index
either must be a run-time constant of type int
or float
, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle.7. ldc and ldc_w从Java语言的视角,有一个
HelloWorld
类,代码如下:public class HelloWorld {
private String str001 = "str001";
// ... ... 省略255个
private String str257 = "str257";
public void test() {
String str = "str258";
}public static void main(String[] args) {
String format = "private String str%03d = \\"str%03d\\";
";
for (int i = 1;
i <
258;
i++) {
String line = String.format(format, i, i);
System.out.println(line);
}
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: ldc_w#516// String str258
3: astore_1
4: return
...
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitLdcInsn("str258");
methodVisitor.visitVarInsn(ASTORE, 1);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 2);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: ldc_w#516// {this} | {String}
0003: astore_1// {this, String} | {}
0004: return// {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →..., value
Format
ldc_w
indexbyte1
indexbyte2
The unsigned
indexbyte1
and indexbyte2
are assembled into an unsigned 16-bit index into the run-time constant pool of the current class, where the value of the index
is calculated as (indexbyte1 &
lt;
&
lt;
8) | indexbyte2
. The index must be a valid index into the run-time constant pool of the current class. The run-time constant pool entry at the index either must be a run-time constant of type int
or float
, or a reference to a string literal, or a symbolic reference to a class, method type, or method handle.推荐阅读
- 如何在Android中使用JSCH(SFTP)将文件上传到服务器
- 如何使用JavaScript确定Google地图上特定位置的用户点击的当前坐标
- JS Web开发的服务在哪里使用
- 如何使ACE Editor实例由用户使用拖放条动态调整大小
- 如何使用JavaScript在浏览器中检索MP3 / WAV音频文件的持续时间
- 如何显示使用JSCH(SFTP)Android进行上传和下载的进度
- @Override注释在Java中是什么意思
- 如何在Java AWT Toolkit中更改框架的标题栏图标(应用程序图标)
- 如何在Android中使用JSCH(SFTP)列出远程路径