public class JavaToDex{
public static void main(String[] args){
System.out.println("How to make java to dex");
}
}
保存文件需要注意,要以类名进行结尾,这是java语言编程的一个特色。
使用javac命名转化java程序转化为class文件。
javac JavaToDex.java ==> JavaToDex.class
java JavaToDex ==> output sth
注意,这个工具并在aosp下,其实想一想也是,dx是为了将java转化dex文件,那么,至少这个工作是由sdk提供的。一般来说,这个工具存放在build-tools下。
usage:
dx --dex [--debug] [--verbose] [--positions=<style>] [--no-locals]
[--no-optimize] [--statistics] [--[no-]optimize-list=<file>] [--no-strict]
[--keep-classes] [--output=<file>] [--dump-to=<file>] [--dump-width=<n>]
[--dump-method=<name>[*]] [--verbose-dump] [--no-files] [--core-library]
[--num-threads=<n>] [--incremental] [--force-jumbo] [--no-warning]
[--multi-dex [--main-dex-list=<file> [--minimal-main-dex]]
[--input-list=<file>] [--min-sdk-version=<n>]
[--allow-all-interface-method-invokes]
[<file>.class | <file>.{zip,jar,apk} | <directory>] ...
Convert a set of classfiles into a dex file, optionally embedded in a
jar/zip. Output name must end with one of: .dex .jar .zip .apk or be a
directory.
Positions options: none, important, lines.
--multi-dex: allows to generate several dex files if needed. This option is
exclusive with --incremental, causes --num-threads to be ignored and only
supports folder or archive output.
--main-dex-list=<file>: <file> is a list of class file names, classes
defined by those class files are put in classes.dex.
--minimal-main-dex: only classes selected by --main-dex-list are to be put
in the main dex.
--input-list: <file> is a list of inputs.
Each line in <file> must end with one of: .class .jar .zip .apk or be a
directory.
--min-sdk-version=<n>: Enable dex file features that require at least sdk
version <n>.
dx --annotool --annotation=<class> [--element=<element types>]
[--print=<print types>]
dx --dump [--debug] [--strict] [--bytes] [--optimize]
[--basic-blocks | --rop-blocks | --ssa-blocks | --dot] [--ssa-step=<step>]
[--width=<n>] [<file>.class | <file>.txt] ...
Dump classfiles, or transformations thereof, in a human-oriented format.
dx --find-usages <file.dex> <declaring type> <member>
Find references and declarations to a field or method.
<declaring type> is a class name in internal form, like Ljava/lang/Object;
<member> is a field or method name, like hashCode.
dx -J<option> ... <arguments, in one of the above forms>
Pass VM-specific options to the virtual machine that runs dx.
dx --version
Print the version of this tool (1.16).
dx --help
Print this message.
上面的这个是帮助文档,值得需要注意下的。 Convert a set of classfiles into a dex file, optionally embedded in a jar/zip. Output name must end with one of: .dex .jar .zip .apk or be a directory.
由此看来,dx可以转化的文件格式还是很多的。
dx --dex --output=JavaToDex2.dex JavaToDex.class
就会由dex文件生成class文件。
好了, 生成dex文件只是万里长征的第一步,后面才是真正的旅途。
如果想查看dex文件的格式(如果有必要的话,这一步为了研究art的东西,一定需要研究这个文件)
有一个比较好的东西是dexdump,唉,这个工具又和dx不同了,dexdump 看样子在aosp中需要的很多,那么,这个文件会直接生成在out/host/linux-x86/bin下。
dexdump -h
dexdump: no file specified
Copyright (C) 2007 The Android Open Source Project
dexdump: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...
-c : verify checksum and exit
-d : disassemble code sections
-f : display summary information from file header
-h : display file header details
-i : ignore checksum failures
-l : output layout, either 'plain' or 'xml'
-m : dump register maps (and nothing else)
-t : temp file name (defaults to /sdcard/dex-temp-*)
我们来看看上面那个文件的具体展示:
vimer@host:~/src/aosp/out/host/linux-x86/bin$ dexdump JavaToDex.dex
Processing 'JavaToDex.dex'...
Opened 'JavaToDex.dex', DEX version '035'
Class #0 -
Class descriptor : 'LJavaToDex;'
Access flags : 0x0001 (PUBLIC)
Superclass : 'Ljava/lang/Object;'
Interfaces -
Static fields -
Instance fields -
Direct methods -
#0 : (in LJavaToDex;)
name : '<init>'
type : '()V'
access : 0x10001 (PUBLIC CONSTRUCTOR)
code -
registers : 1
ins : 1
outs : 1
insns size : 4 16-bit code units
catches : (none)
positions :
0x0000 line=1
locals :
0x0000 - 0x0004 reg=0 this LJavaToDex;
#1 : (in LJavaToDex;)
name : 'main'
type : '([Ljava/lang/String;)V'
access : 0x0009 (PUBLIC STATIC)
code -
registers : 3
ins : 1
outs : 2
insns size : 8 16-bit code units
catches : (none)
positions :
0x0000 line=3
0x0007 line=4
locals :
Virtual methods -
source_file_idx : 2 (JavaToDex.java)
这个也是后续研究dex2oat的基础。
继续自己写文章的记叙风格,先把不熟悉的东西感性的介绍下,后面深入研究后再 介绍多一些。
很简单的说就是,在c++11中,某些人就是为了偷懒,对于某些变量的声明变的不耐烦, 想即时使用。这一点和我们经常用的解释性编程语言具有很大的相似性。比如,我们的 python shell都是这种用法,c++11的auto就在感官上做到了这一点。
int main(){
auto str = "yubo and chun \n";
std::cout << str << endl;
}
这里我们就可以清楚了,auto可以节省显式地声明类型了,这一点尤其在自定义的很多 类 容器时具有巨大的帮助
下面这一个例子加强了这种概念:
#include <iostream>
using namespace std;
template<typename T1, typename T2>
float Sum(T1& t1, T2& t2){
auto a = t1 + t2;
return a;
}
int main(){
int a = 3;
long b = 5;
float c = 1.0f;
float d = 2.3f;
auto e = Sum<int, long>(a, b);
auto f = Sum<float, float>(c, d);
cout << e << endl << f << endl;
}
上面这段程序有一个目前我不了解的地方就是,如果定义Sum的返回值类型为int,则f返回int(这一点是对的,那么,怎么可以让函数返回值使用模板呢)
任何东西都有两面性,auto也不例外,目前我使用auto的情况也不是特别多,所以关于这一点,我暂且放下,等到我有更深的认识后再补充上。
其实,对于整个汇编系统而言,在下实在是没有入门,别说riscv了,就是最常用的x86也没有精通一点半星的, 更别说arm了,当然,这里这篇文件介绍 riscv主要是由于工作之中会偶尔遇到,姑且碰上什么就记录什么吧。
(gdb) disassemble /mr main
Dump of assembler code for function main:
7 {
0x0000000000027936 <+0>: 41 11 addi sp,sp,-16
8 int a=10;
9 int b=10;
10 printf("Hello world\n");
0x000000000002793a <+4>: 17 a5 fe ff auipc a0,0xfffea
0x000000000002793e <+8>: 13 05 f5 bf addi a0,a0,-1025 # 0x11539
0x0000000000027942 <+12>: 97 20 02 00 auipc ra,0x22
0x0000000000027946 <+16>: e7 80 20 a2 jalr -1502(ra) # 0x49364 <puts(char const*)>
11 printf("int a+b = %d\n", sum(a, b));
0x000000000002794a <+20>: 17 c5 fe ff auipc a0,0xfffec
--Type <RET> for more, q to quit, c to continue without paging--
0x000000000002794e <+24>: 13 05 55 62 addi a0,a0,1573 # 0x13f6f
0x0000000000027952 <+28>: d1 45 li a1,20
0x0000000000027954 <+30>: 97 20 02 00 auipc ra,0x22
0x0000000000027958 <+34>: e7 80 00 98 jalr -1664(ra) # 0x492d4 <printf(char const*, ...)>
12 return 0;
0x000000000002795c <+38>: 01 45 li a0,0
0x000000000002795e <+40>: a2 60 ld ra,8(sp)
0x0000000000027960 <+42>: 41 01 addi sp,sp,16
0x0000000000027962 <+44>: 82 80 ret
下面是简单的介绍这个汇编出现的指令。 在这里,在下向各位报一声歉,因为我写文章大部分 都是给自己写的,基本上写到哪里就算哪里了,导致文章大部分残缺不全,这也是今后我需要改进 的部分。
The AUIPC instruction, which adds a 20-bit upper immediate to the PC, replaces the RDNPC instruction, which only read the current PC value. This results in significant savings for position-independent code. 这个指令的解释也很清楚,但是在这里想愚蠢的问一下,为什么会送到pc中去,虽然都说pc需要存储 下一条执行的地址。
0x000000000002793a <+4>: 17 a5 fe ff auipc a0,0xfffea
看这样子是将0xfffea(20 bit)放入a0寄存器中,剩下的位自然是填充0.
10060: fe010113 addi sp,sp,-32 # allocate space
10064: 00113c23 sd ra,24(sp) # save $ra
10068: 00813823 sd s0,16(sp) # save $s0
1006c: 02010413 addi s0,sp,32 # set up $s0 as frame pointer
安卓有很多的log系统,以aosp为例,最基本的log定义恐怕是 system\core\base\include\android-base\Logging.h:
//
// Google-style C++ logging.
//
// This header provides a C++ stream interface to logging.
//
// To log:
//
// LOG(INFO) << "Some text; " << some_value;
//
// Replace `INFO` with any severity from `enum LogSeverity`.
//
// To log the result of a failed function and include the string
// representation of `errno` at the end:
//
那么对应的 log等级有:
num LogSeverity {
VERBOSE,
DEBUG,
INFO,
WARNING,
ERROR,
FATAL_WITHOUT_ABORT,
FATAL,
};
如果可以研究下将INFO改为FATAl(可以带有call stack).
借助这个log系统,aosp 中其他各个子模块可以实现自己的log系统,以art为例:art\libartbase\base\logging.h
#include "android-base/logging.h"
#include "macros.h
请注意这个include文件,我自己并没有在该上层目录的Android.bp文件中找到相关头文件的引用,这块是怎么解决的这个问题,还需要研究。
本系列是根据 SCott Meyers 的大作«overview of the new c++(c++11/14)»进行练习总结。 因为我本身对c++的使用还不是特别的熟悉,所以,在阅读本系列的过程中,在对一些新的特性进行 阐述的时候,可能会显得尤其啰嗦,这也符合我一贯的行文习惯,不好,这点得改。
BTW, 为什么这么着急的去看一些 c++的东西呢? 因为aosp的大部分是C++写的啊,作为AOSP的使用者 ,能不了解C++最新的技术吗?
拷贝构造函数是一种将对象初始化的方式,除了那种带有参数的构造函数外,这也算一种很常见的赋值对象的方式。
#include <iostream>
using namespace std;
class Point {
private:
int x, y;
public:
Point(int x1, int y1){x = x1, y = y1 ;} // Directly constructor
// 另一种给构造函数赋初始值的方式是
// 成员列表的形式: Point(int x1, int y1) : x(x1), y(y1){}
// 这种方式只能类内使用
Point(const Point &p2) { x = p2.x, y = p2.y ;} // copy constructor
int getX() { return x ;}
int getY() { return y ;}
};
int main()
{
Point p1(10, 15);
Point p2 = p1; // assign object
cout << p1.getX() << endl;
cout << p2.getY() << endl;
}
std::move是
#include <iostream>
#include <utility>
#include <vector>
#include <string>
using namespace std;
int main(){
std::string str = "hello";
std::vector<std::string> v;
v.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";
v.push_back(std::move(str));
/**
* std::move的使用是将原对象的内容移动至现在的对象,
* 这样的效率很高,代价就是原对象的内容被移动后有可能为空
*/
std::cout << "After move, str is \"" << str << "\"\n";
std::cout << "The contents of the vector are " << v[0] << " the v[1]" << v[0] << std::endl;
}
Output:
After copy, str is "hello"
After move, str is ""
The contents of the vector are hello the v[1]hello
std::move的解释 .下面需要补充几个概念。
一般来说,可以取地址的是左值,不能取地址的是右值。那么,什么对象可以取地址,又有哪些量是不可以取地址的呢?
左值的声明符号为&,右值的声明符号为&&。
为什么引入了std::move?不知道在哪里看到过这样的笑话,说是一个hello,world的程序c++的表达式可以复制出200份的内容,这显然夸张,但是稍微复杂的构造函数列表那是真的恐怖,所以,上面的测试你也已经看到了效果,那就是原对象不再保存这份内容了。 主要参考这篇文章
# o以下操作仅针对debian系。
sudo apt install samba
在samba的系统配置文件/etc/samba/smb.conf中, 添加以下内容:
[share]
path = /home/vimer/pic
public = yes
writable = yes
valid users = vimer
create mask = 0644
force create mode = 0644
directory mask = 0755
force directory mode = 0755
available = yes
配置文件修改完成后,需要使用smbpasswd命令去添加smb的用户,使用手工创建smb 用户的方式是不正确的。
参考 https://blog.csdn.net/qq_29129381/article/details/106826108
service smb start # 来开启服务
smbpasswd -a XXX # 来增加用户名密码
smbpasswd -e xxx # 启用用户名
service smb restart # 重启服务
service iptables stop # 关闭防火墙
注意, debian中使用smbd。
sudo service smbd restart 注意这里的smbd因为这个耽误自己很长时间的。
在windows中可以在文件管理器
\\ip\dir,其中dir就是上面配置文件中的设置的分享路径别名,比如,我的上面就是 share.
哈哈 第一个就是 sublime open-> file folder