2010年12月16日
#
http://viralpatel.net/blogs/2009/12/tutorial-create-struts-2-application-eclipse-example.html problem:
HTTP Status 500
java.lang.NullPointerException
org.apache.struts2.impl.StrutsActionProxy.getErrorMessage(StrutsActionProxy.java:69)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
resolve problem:
1. struts.xml should under src
2. in struts.xml:
<action name="login" method="
excute" class="net.viralpatel.struts2.LoginAction">
24.Sep.2009 | by Gusac | Filed in: Articles, Tutorials
With the lack of Graphical Interface on Windows 2008 Core server there comes a need of performing a lot of task through command line. One of which is checking file properties like file version, path, product verision etc. Luckily we have a command that makes this task simple. On a side note, We can also run the same command on other operating systems like Windows Xp, 2003, vista.
Here is the command:
wmic datafile where name='c:\\windows\\system32\\notepad.exe'
Click here to view the enlarged screenshot
Notice that we have used two backslashes \\ in the file path. Also, notice that the path is enclosed in the single quotes.
The output will be confusing to read in command prompt window. To read and understand it better, we can take the output in text format and read it in notepad.
While doing so, please do NOT wrap the text.
wmic datafile where name='c:\\windows\\system32\\notepad.exe' > out.txt

Click here to view the enlarged screenshot
The output will reveal the file properties like Hidden, Path, Drive, Version Caption, Access rights etc.
To get one particular property of a file we need to modify the command a little bit. We need to use the GET Alias injunction to the command mentioned above. Let's say we want to check the version for the file notepad.exe. The command that is used for this is:
wmic datafile where name='c:\\windows\\system32\\notepad.exe' get version
Similarily, there is a list of properties that can be fetched through this command line. They are:
Access Rights
Caption
Class Name
Compressed
Compression Method
Computer System Class Name
Computer System Name
Creation Date
Current File Open Count
Description
Drive
Eight Dot Three File Name
Encrypted
Encryption Method
File Extension
File Name
File System Class Name
File System Name
File Type
Hidden
Install Date
Last Accessed
Last Modified
Manufacturer
Name
Path
Readable
Should Be Archived
Size
Status
System File
Version
Writeable
from
http://www.iis.net/ConfigReference/system.webServer/security/authentication/windowsAuthentication
The <windowsAuthentication>
element defines configuration settings for the Internet Information Services (IIS) 7 Windows authentication module. You can use Windows authentication when your IIS 7 server runs on a corporate network that is using Microsoft Active Directory service domain identities or other Windows accounts to identify users. Because of this, you can use Windows authentication whether or not your server is a member of an Active Directory domain.
Windows authentication (formerly named NTLM, and also referred to as Windows NT Challenge/Response authentication) is a secure form of authentication because the user name and password are hashed before being sent across the network. When you enable Windows authentication, the client browser sends a strongly hashed version of the password in a cryptographic exchange with your Web server.
Windows authentication supports two authentication protocols, Kerberos and NTLM, which are defined in the <providers>
element. When you install and enable Windows authentication on IIS 7, the default protocol is Kerberos. The <windowsAuthentication>
element can also contain a useKernelMode attribute that configures whether to use the kernel mode authentication feature that is new to Windows Server 2008.
Windows authentication is best suited for an intranet environment for the following reasons:
- Client computers and Web servers are in the same domain.
- Administrators can make sure that every client browser is Internet Explorer 2.0 or later.
- HTTP proxy connections, which are not supported by NTLM, are not required.
- Kerberos version 5 requires a connection to Active Directory, which is not feasible in an Internet environment.
New in IIS 7.5
The <extendedProtection>
element was introduced in IIS 7.5, which allows you to configure the settings for the new extended protection features that have been integrated into Windows authentication.
Version |
Notes |
IIS 7.5 |
The <extendedProtection> element was added in IIS 7.5. |
IIS 7.0 |
The <windowsAuthentication> element was introduced in IIS 7.0. |
IIS 6.0 |
The <windowsAuthentication> element replaces portions of the IIS 6.0 AuthType and AuthFlags metabase properties. |
The default installation of IIS 7 does not include the Windows authentication role service. To use Windows authentication on IIS, you must install the role service, disable Anonymous authentication for your Web site or application, and then enable Windows authentication for the site or application.
Note: After you install the role service, IIS 7 commits the following configuration settings to the ApplicationHost.config file.
<windowsAuthentication enabled="false" />
Windows Server 2008 or Windows Server 2008 R2
- On the taskbar, click Start, point to Administrative Tools, and then click Server Manager.
- In the Server Manager hierarchy pane, expand Roles, and then click Web Server (IIS).
- In the Web Server (IIS) pane, scroll to the Role Services section, and then click Add Role Services.
- On the Select Role Services page of the Add Role Services Wizard, select Windows Authentication, and then click Next.
- On the Confirm Installation Selections page, click Install.
- On the Results page, click Close.
Windows Vista or Windows 7
- On the taskbar, click Start, and then click Control Panel.
- In Control Panel, click Programs and Features, and then click Turn Windows Features on or off.
- Expand Internet Information Services, then World Wide Web Services, then Security.
- Select Windows Authentication, and then click OK.
How to enable Windows authentication for a Web site, Web application, or Web service
- Open Internet Information Services (IIS) Manager:
- If you are using Windows Server 2008 or Windows Server 2008 R2:
- On the taskbar, click Start, point to Administrative Tools, and then click Internet Information Services (IIS) Manager.
- If you are using Windows Vista or Windows 7:
- On the taskbar, click Start, and then click Control Panel.
- Double-click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
- In the Connections pane, expand the server name, expand Sites, and then the site, application, or Web service for which you want to enable Windows authentication.
- Scroll to the Security section in the Home pane, and then double-click Authentication.
- In the Authentication pane, select Windows Authentication, and then click Enable in the Actions pane.
How to enable Extended Protection for Windows authentication
- Open Internet Information Services (IIS) Manager:
- If you are using Windows Server 2008 or Windows Server 2008 R2:
- On the taskbar, click Start, point to Administrative Tools, and then click Internet Information Services (IIS) Manager.
- If you are using Windows Vista or Windows 7:
- On the taskbar, click Start, and then click Control Panel.
- Double-click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
- In the Connections pane, expand the server name, expand Sites, and then the site, application, or Web service for which you want to enable Extended Protection for Windows authentication.
- Scroll to the Security section in the Home pane, and then double-click Authentication.
- In the Authentication pane, select Windows Authentication.
- Click Enable in the Actions pane.
- Click Advanced Settings in the Actions pane.
- When the Advanced Settings dialog box appears, select one of the following options in the Extended Protection drop-down menu:
- Select Accept if you want to enable extended protection while providing down-level support for clients that do not support extended protection.
- Select Required if you want to enable extended protection without providing down-level support.
- Click OK to close the Advanced Settings dialog box.
The <windowsAuthentication>
element is configurable at the site, application, or virtual directory level in the ApplicationHost.config file.
Attributes
Attribute |
Description |
authPersistNonNTLM |
Optional Boolean attribute.
Specifies whether IIS automatically reauthenticates every non-NTLM (for example, Kerberos) request, even those on the same connection. False enables multiple authentications for the same connections.
Note: A setting of true means that the client will be authenticated only once on the same connection. IIS will cache a token or ticket on the server for a TCP session that stays established.
The default is false . |
authPersistSingleRequest |
Optional Boolean attribute.
Setting this flag to true specifies that authentication persists only for a single request on a connection. IIS resets the authentication at the end of each request, and forces reauthentication on the next request of the session.
The default value is false . |
enabled |
Required Boolean attribute.
Specifies whether Windows authentication is enabled.
The default value is false . |
useKernelMode |
Optional Boolean attribute.
Specifies whether Windows authentication is done in kernel mode. True specifies that Windows authentication uses kernel mode.
Kernel-mode authentication may improve authentication performance and prevent authentication problems with application pools that are configured to use a custom identity.
As a best practice, do not disable this setting if you use Kerberos authentication and have a custom identity on the application pool.
The default is true . |
Child Elements
Element |
Description |
extendedProtection |
Optional element.
Specifies extended protection options for Windows authentication.
Note: This element was added in IIS 7.5. |
providers |
Optional element.
Specifies security support providers used for Windows authentication. |
Configuration Sample
The following default <windowsAuthentication>
element is configured at the root ApplicationHost.config file in IIS 7.0, and disables Windows authentication by default. It also defines the two Windows authentication providers for IIS 7.0.
<windowsAuthentication enabled="false">
<providers>
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
The following example enables Windows authentication and disables Anonymous authentication for a Web site named Contoso.
<location path="Contoso">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
The following examples disable Anonymous authentication for a site named Contoso, then enable Windows authentication for the site.
AppCmd.exe
appcmd.exe set config "Contoso" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:"False" /commit:apphost
appcmd.exe set config "Contoso" -section:system.webServer/security/authentication/windowsAuthentication /enabled:"True" /commit:apphost
Note: You must be sure to set the commit parameter to apphost
when you use AppCmd.exe to configure these settings. This commits the configuration settings to the appropriate location section in the ApplicationHost.config file.
C#
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample {
private static void Main() {
using(ServerManager serverManager = new ServerManager()) {
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection anonymousAuthenticationSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", "Contoso");
anonymousAuthenticationSection["enabled"] = false;
ConfigurationSection windowsAuthenticationSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", "Contoso");
windowsAuthenticationSection["enabled"] = true;
serverManager.CommitChanges();
}
}
}
VB.NET
Imports System
Imports System.Text
Imports Microsoft.Web.Administration
Module Sample
Sub Main()
Dim serverManager As ServerManager = New ServerManager
Dim config As Configuration = serverManager.GetApplicationHostConfiguration
Dim anonymousAuthenticationSection As ConfigurationSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", "Contoso")
anonymousAuthenticationSection("enabled") = False
Dim windowsAuthenticationSection As ConfigurationSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", "Contoso")
windowsAuthenticationSection("enabled") = True
serverManager.CommitChanges()
End Sub
End Module
JavaScript
var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var anonymousAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/anonymousAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso");
anonymousAuthenticationSection.Properties.Item("enabled").Value = false;
var windowsAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/windowsAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso");
windowsAuthenticationSection.Properties.Item("enabled").Value = true;
adminManager.CommitChanges();
VBScript
Set adminManager = CreateObject("Microsoft.ApplicationHost.WritableAdminManager")
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST"
Set anonymousAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/anonymousAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso")
anonymousAuthenticationSection.Properties.Item("enabled").Value = False
Set windowsAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/windowsAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso")
windowsAuthenticationSection.Properties.Item("enabled").Value = True
adminManager.CommitChanges()
how to check window version
run: Winver
Here's How:
-
Open the System Information
Open the Start menu, and click on Programs -> Accessories -> System Tools -> System Information
-
Look in the System Summary
The System Information tool will display detailed information about your Windows operating system. Once opened it will show the "System Summary" – it’s an overview of your computer and operating system.
-
Look for the System Type Item
On the right hand side of the window you will see a list of items. Look for the item called "System Type".
The value of this item will tell you whether your computer is 32-bit or 64-bit:
- x86-based PC: It’s a 32-bit computer.
- x64-based PC: It’s a 64-bit computer.
摘要: ContentProvider何時創(chuàng)建呢?這是一個值得深思的問題?
據(jù)我這兩天的了解是在你要用到的時候才會調用ContentProvider的onCreate函數(shù)進行創(chuàng)建。你就會什么時候叫要用到的時候呢?比如你要查詢或刪除修改數(shù)據(jù)庫的時候通過ContentResolver的quire或delete來操縱數(shù)據(jù)時就會調用ContentProvider的onCreate函數(shù),若已經創(chuàng)建了數(shù)...
閱讀全文
View是在onTouchEvent(MotionEvent event)里對用戶的動作做了一定的分析,從而通知我們是發(fā)生了點擊還是長按等事件。
我們需要創(chuàng)建一個GestureDetector的對象,傳入listener對象,view接收到的onTouchEvent中將event傳給GestureDetector進行分析,listener會回調給我們相應的動作。其中GestureDetector.SimpleOnGestureListener(Framework幫我們簡化了)是實現(xiàn)了上面提到的OnGestureListener和OnDoubleTapListener兩個接口的類,我們只需要繼承它并重寫其中我們關心的回調即可。
,那么,這個類如何使用呢?以下是使用該類的一個范例:
private GestureDetector mGestureDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGestureDetector = new GestureDetector(this, new MyGestureListener());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
/* 有關上面的 onTouchEvent方法,我們可以直接判斷MotionEvent的類型,
對于手勢移動僅僅捕獲ACTION_MOVE即可,
我們通過參數(shù)MotionEvent e1, MotionEvent e2,float distanceX, float distanceY可以獲取操作變化。
比如 distanceX > 0 向右邊移動,distanceX < 0 則向左邊,distanceY > 0 向上滾動, distanceY < 0 向下滾動。
*/
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onSingleTapUp(MotionEvent ev) {
Log.d("onSingleTapUp",ev.toString());
return true;
}
@Override
public void onShowPress(MotionEvent ev) {
Log.d("onShowPress",ev.toString());
}
@Override
public void onLongPress(MotionEvent ev) {
Log.d("onLongPress",ev.toString());
}
}
更多的回調消息,方便的對用戶的動作進行響應
public interface OnGestureListener {
// Touch down時觸發(fā), e為down時的MotionEvent
boolean onDown(MotionEvent e);
// 在Touch down之后一定時間(115ms)觸發(fā),e為down時的MotionEvent
void onShowPress(MotionEvent e);
// Touch up時觸發(fā),e為up時的MotionEvent
boolean onSingleTapUp(MotionEvent e);
// 滑動時觸發(fā),e1為down時的MotionEvent,e2為move時的MotionEvent
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
// 在Touch down之后一定時間(500ms)觸發(fā),e為down時的MotionEvent
void onLongPress(MotionEvent e);
// 滑動一段距離,up時觸發(fā),e1為down時的MotionEvent,e2為up時的MotionEvent
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}
public interface OnDoubleTapListener {
// 完成一次單擊,并確定沒有二擊事件后觸發(fā)(300ms),e為down時的MotionEvent
boolean onSingleTapConfirmed(MotionEvent e);
// 第二次單擊down時觸發(fā),e為第一次down時的MotionEvent
boolean onDoubleTap(MotionEvent e);
// 第二次單擊down,move和up時都觸發(fā),e為不同時機下的MotionEvent
boolean onDoubleTapEvent(MotionEvent e);
}
boolean onDoubleTap(MotionEvent e)
解釋:雙擊的第二下Touch down時觸發(fā)
boolean onDoubleTapEvent(MotionEvent e)
解釋:雙擊的第二下Touch down和up都會觸發(fā),可用e.getAction()區(qū)分。
boolean onDown(MotionEvent e)
解釋:Touch down時觸發(fā)
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
解釋:Touch了滑動一點距離后,up時觸發(fā)。
void onLongPress(MotionEvent e)
解釋:Touch了不移動一直Touch down時觸發(fā)
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
解釋:Touch了滑動時觸發(fā)。
void onShowPress(MotionEvent e)
解釋:Touch了還沒有滑動時觸發(fā)
(與onDown,onLongPress比較,onDown只要Touch down一定立刻觸發(fā)。而Touchdown后過一會沒有滑動先觸發(fā)onShowPress再是onLongPress。
所以Touchdown后一直不滑動,onDown->onShowPress->onLongPress這個順序觸發(fā)。
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋:上面這兩個函數(shù)都是在touch down后又沒有滑動(onScroll),又沒有長按(onLongPress),然后Touchup時觸發(fā)。
點擊一下非常快的(不滑動)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點擊一下稍微慢點的(不滑動)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
protected void onNewIntent (Intent intent)
This is called for activities that set launchMode to "singleTop" in their package, or if a client used theFLAG_ACTIVITY_SINGLE_TOP
flag when calling startActivity(Intent)
. In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
An activity will always be paused before receiving a new intent, so you can count on onResume()
being called after this method.
Note that getIntent()
still returns the original Intent. You can use setIntent(Intent)
to update it to this new Intent.
在IntentActivity中重寫下列方法:onCreate onStart onRestart onResume onPause onStop onDestroy onNewIntent
一、其他應用發(fā)Intent,執(zhí)行下列方法:
I/@@@philn(12410): onCreate
I/@@@philn(12410): onStart
I/@@@philn(12410): onResume
發(fā)Intent的方法:
Uri uri = Uri.parse("philn://blog.163.com");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
二、接收Intent聲明:
<activity android:name=".IntentActivity" android:launchMode="singleTask"
android:label="@string/testname">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="philn"/>
</intent-filter>
</activity>
三、如果IntentActivity處于任務棧的頂端,也就是說之前打開過的Activity,現(xiàn)在處于
I/@@@philn(12410): onPause
I/@@@philn(12410): onStop 狀態(tài)的話
其他應用再發(fā)送Intent的話,執(zhí)行順序為:
I/@@@philn(12410): onNewIntent
I/@@@philn(12410): onRestart
I/@@@philn(12410): onStart
I/@@@philn(12410): onResume
引言:
設計模式是經驗的文檔化。它是對被用來在特定場景下解決一般設計問題的類和相互通信的對象的描述。更通俗的來說,它是一個問題/解決方案對。一旦我們掌握了設計模式,就等于擁有了一支強有力的專家隊伍。它甚至能夠使面向對象的新手利用前人的經驗找出職責明確的類和對象,從而獲得優(yōu)雅的解決方案。由于設計模式也是重構的目標,如果在設計的初期適當?shù)匾朐O計模式,可以減少重構的工作量。
但是,我們也不能陷入模式的陷阱,為了使用模式而去套模式,那樣會陷入形式主義。我們在使用模式的時候,一定要注意模式的意圖(intent),而不要過多的去關注模式的實現(xiàn)細節(jié),因為這些實現(xiàn)細節(jié)在特定情況下,可能會發(fā)生一些改變。不要頑固地認為設計模式一書中的類圖或實現(xiàn)代碼就代表了模式本身。
下面,我們來討論一下為什么要在分布式、多層系統(tǒng)中使用Observer模式。
多層體系結構(multi-tier architecture):
三層體系結構是多層體系結構中最簡單的一種,它一般包括:
- 表示層(presentation)-窗口、報表-
- 業(yè)務邏輯層(business logic)-管理業(yè)務過程的任務和規(guī)則。它又可以細分為領域對象層(代表領域概念)和服務層(提供數(shù)據(jù)庫交互、安全性、打印報表)。
- 存儲層(storage)-持久化存儲機制。如數(shù)據(jù)庫服務器等。
圖一:三層體系結構
而Java 2平臺企業(yè)版(J2EE)是一種利用Java 2平臺來簡化諸多與多級企業(yè)解決方案的開發(fā)、部署和管理相關的復雜問題的體系結構。它是開放的、基于標準的平臺,用以開發(fā)、部署和管理N層結構、面向Web的,以服務器為中心的企業(yè)級應用。
為了支持領域對象的復用,并且使領域對象的接口變更所帶來的影響最小化。我們將領域層(模型)和表示層(視圖)相分離。
采用模型-視圖模式的意義在于:
- 支持聚合度更高的模型定義,使模型的定義可以集中在領域過程的定義,而不是圖形界面上。
- 允許將模型和用戶界面并行開發(fā)。
- 使用戶界面的需求變化對領域層所造成的影響最小化。
- 允許建立與一個現(xiàn)有的領域層對象相連接的新視圖,同時不影響領域層。
- 允許一個模型同時有多個視圖,例如使用SVG和表格。
- 允許模型層獨立于用戶界面層執(zhí)行。
而這恰恰與Observer模式的意圖相吻合。因此我們有必要跨層來實現(xiàn)Observer模式。
其實,在應用中更多的是采用MVC框架來架構整個企業(yè)應用的。在MVC框架中,Model和View之間存在著依賴關系,是Observer模式的典型應用。當然MVC框架還包括其它模式如Composite模式和Strategy模式。在J2EE平臺中,我們可以把Web Tier(包括Jsp和servelet和JavaBean)看作是表示層,EJB Tier看作是領域層。而controller可能跨距Web Tier和 EJB Tier。
在Java類庫中采用Java.util.Observable類和Java.util.Observer接口來實現(xiàn)Observer模式,它們在單個的Java VM.中運行的很好,但如果想在EJB中使用它們就會有一些問題。這正如我們引言中提到的,模式的具體實現(xiàn)在特定情況下,可能會發(fā)生一些改變。
值傳遞還是遠程引用傳遞?
值傳遞:
在Java RMI中要求所有的參數(shù)和返回類型是JAVA的基本類型或實現(xiàn)Java.io.Serilizable的對象。串行化對象通過值傳遞(又名拷貝傳遞),而不是引用傳遞,這意味著在某一層中串行化對象的更并不自動影響到其它的對象。
遠程引用傳遞:
對于EJB對象而言,它由兩個接口(home接口和remote接口)和一個類組成。容器會根據(jù)ejb規(guī)范來生成實現(xiàn)上面兩個接口的類(我們分別稱為xxxEJBHome對象和xxxEjbObject對象)。在較多的容器的實現(xiàn)方案中,xxxEJBHome對象使用了factory模式來創(chuàng)建xxxEjbObject對象;xxxEjbObject對象則采用proxy模式,作為xxxBean的代理類。在生成以上兩個對象的同時,容器會從部署文件中讀取關于安全、事務、持久性等服務并在xxxEjbObject對象和xxxEJBHome對象中添加以上服務的代碼。而且xxxEJBHome對象和xxxEjbObject對象都是分布式對象,我們在此只討論xxxEjbObject對象。所謂分布式對象,從本質上來講,分為3個部分:object server、skeleton、stub。其中object server和skeleton位于服務器端,而stub位于客戶端。Object server負責實現(xiàn)業(yè)務邏輯,skeleton負責marshal和unmarshal方法簽名。
圖二:分布式對象
顯然,EJB的客戶(調用EJB的對象)可以是任何對象,包括EJB和一般的Java類甚至是用任何語言寫的corba客戶端。
從EJB的客戶視角來看的話,我們只能看到一個home接口、一個remote接口(對于實體bean的話,還可以看見一個主鍵類,而bean類對客戶是不可見的)。但我們從上面的論述,我們可以知道,對于remote接口中地方法調用,實際上是多態(tài)地調用XXX_Stub類。即XXX_Stub對象對客戶具有可見性(但這種可見性是透明的,即客戶不知道這種可見性的存在)。由于,XXX_Stub對象和Object Server實現(xiàn)了相同的接口,并且Object server真正實現(xiàn)了業(yè)務邏輯。所以,當在客戶端調用XXX_Stub對象的方法時候,XXX_Stub對象通過socket通信機制將方法簽名傳給XXX_Skeleton對象,XXX_Skeleton對象在去委托Object Server完成業(yè)務處理邏輯。因此,Object Server本身發(fā)生了改變。我們稱XXX_Stub對象是Object Server對象的遠程引用,并認為當分布式對象作為參數(shù)傳遞的時候,是通過引用傳遞的(會產生副作用
RMI的定義
Java RMI (Remote Method Invocation 遠程方法調用)是用Java在JDK1.1中實現(xiàn)的,它大大增強了Java開發(fā)分布式應用的能力。Java作為一種風靡一時的網(wǎng)絡開發(fā)語言,其巨大的威力就體現(xiàn)在它強大的開發(fā)分布式網(wǎng)絡應用的能力上,而RMI就是開發(fā)百分之百純Java的網(wǎng)絡分布式應用系統(tǒng)的核心解決方案之一。其實它可以被看作是RPC的Java版本。但是傳統(tǒng)RPC并不能很好地應用于分布式對象系統(tǒng)。而Java RMI 則支持存儲于不同地址空間的程序級對象之間彼此進行通信,實現(xiàn)遠程對象之間的無縫遠程調用。
RMI目前使用Java遠程消息交換協(xié)議JRMP(Java Remote Messaging Protocol)進行通信。JRMP是專為Java的遠程對象制定的協(xié)議。因此,Java RMI具有Java的“Write Once,Run Anywhere”的優(yōu)點,是分布式應用系統(tǒng)的百分之百純Java解決方案。用Java RMI開發(fā)的應用系統(tǒng)可以部署在任何支持JRE(Java Run Environment Java,運行環(huán)境)的平臺上。但由于JRMP是專為Java對象制定的,因此,RMI對于用非Java語言開發(fā)的應用系統(tǒng)的支持不足。不能與用非Java語言書寫的對象進行通信。
RMI 和CORBA常被視為相互競爭的技術,因為兩者都提供對遠程分布式對象的透明訪問。但這兩種技術實際上是相互補充的,一者的長處正好可以彌補另一者的短處。RMI 和 CORBA 的結合產生了 RMI-IIOP,RMI-IIOP 是企業(yè)服務器端 Java 開發(fā)的基礎
1997 年,IBM 和 Sun Microsystems啟動了一項旨在促進 Java 作為企業(yè)開發(fā)技術的發(fā)展的合作計劃。兩家公司特別著力于如何將 Java 用作服務器端語言,生成可以結合進現(xiàn)有體系結構的企業(yè)級代碼。所需要的就是一種遠程傳輸技術,它兼有 Java 的 RMI(Remote Method Invocation,遠程方法調用)較少的資源占用量和更成熟的 CORBA(Common Object Request Broker Architecture,公共對象請求代理體系結構)技術的健壯性。出于這一需要,RMI-IIOP問世了,它幫助將 Java 語言推向了目前服務器端企業(yè)開發(fā)的主流語言的領先地位。
RMI的組成
一個正常工作的RMI系統(tǒng)由下面幾個部分組成:
1、遠程服務的接口定義
2、遠程服務接口的具體實現(xiàn)
3、樁(Stub)和框架(Skeleton)文件
4、一個運行遠程服務的服務器
5、一個RMI命名服務,它允許客戶端去發(fā)現(xiàn)這個遠程服務
6、類文件的提供者(一個HTTP或者FTP服務器)
7、一個需要這個遠程服務的客戶端程序
RMI的實現(xiàn)
下面我們一步一步建立一個簡單的RMI系統(tǒng)。首先在你的機器里建立一個新的文件夾,以便放置我們創(chuàng)建的文件,為了簡單起見,我們只使用一個文件夾存放客戶端和服務端代碼,并且在同一個目錄下運行服務端和客戶端。
如果所有的RMI文件都已經設計好了,那么你需要下面的幾個步驟去生成你的系統(tǒng):
1、 編寫并且編譯接口的Java代碼
2、 編寫并且編譯接口實現(xiàn)的Java代碼
3、 從接口實現(xiàn)類中生成 Stub 和 Skeleton 類文件
4、 編寫遠程服務的主運行程序
5、 編寫RMI的客戶端程序
6、 安裝并且運行RMI系統(tǒng)
1、接口
第一步就是建立和編譯服務接口的Java代碼。這個接口定義了所有的提供遠程服務的功能,下面是源程序:
1. //Calculator.java
2. //define the interface
3. import java.rmi.Remote;
4.
5. public interface Calculator extends Remote
6. {
7. public long add(long a, long b)
8. throws java.rmi.RemoteException;
9.
10. public long sub(long a, long b)
11. throws java.rmi.RemoteException;
12.
13. public long mul(long a, long b)
14. throws java.rmi.RemoteException;
15.
16. public long div(long a, long b)
17. throws java.rmi.RemoteException;
18. }
注意,這個接口繼承自Remote,每一個定義的方法都必須拋出一個RemoteException異常對象。
建立這個文件,把它存放在剛才的目錄下,并且編譯。
>javac Calculator.java
2、接口的具體實現(xiàn)
下一步,我們就要寫遠程服務的具體實現(xiàn),這是一個CalculatorImpl類文件:
1. //CalculatorImpl.java
2. //Implementation
3. import java.rmi.server.UnicastRemoteObject;
4.
5. public class CalculatorImpl extends UnicastRemoteObject implements Calculator
6. {
7.
8. // 這個實現(xiàn)必須有一個顯式的構造函數(shù),并且要拋出一個RemoteException異常
9. public CalculatorImpl()
10. throws java.rmi.RemoteException {
11. super();
12. }
13.
14. public long add(long a, long b)
15. throws java.rmi.RemoteException {
16. return a + b;
17. }
18.
19. public long sub(long a, long b)
20. throws java.rmi.RemoteException {
21. return a - b;
22. }
23.
24. public long mul(long a, long b)
25. throws java.rmi.RemoteException {
26. return a * b;
27. }
28.
29. public long div(long a, long b)
30. throws java.rmi.RemoteException {
31. return a / b;
32. }
33. }
同樣的,把這個文件保存在你的目錄里然后編譯他。
這個實現(xiàn)類使用了UnicastRemoteObject去聯(lián)接RMI系統(tǒng)。在我們的例子中,我們是直接的從UnicastRemoteObject 這個類上繼承的,事實上并不一定要這樣做,如果一個類不是從UnicastRmeoteObject上繼承,那必須使用它的exportObject() 方法去聯(lián)接到RMI。
如果一個類繼承自UnicastRemoteObject,那么它必須提供一個構造函數(shù)并且聲明拋出一個RemoteException對象。當這個構造函數(shù)調用了super(),它久激活UnicastRemoteObject中的代碼完成RMI的連接和遠程對象的初始化。
3、Stubs 和Skeletons
下一步就是要使用RMI編譯器rmic來生成樁和框架文件,這個編譯運行在遠程服務實現(xiàn)類文件上。
>rmic CalculatorImpl
在你的目錄下運行上面的命令,成功執(zhí)行完上面的命令你可以發(fā)現(xiàn)一個Calculator_stub.class文件,如果你是使用的Java2SDK,那么你還可以發(fā)現(xiàn)Calculator_Skel.class文件。
4、主機服務器
遠程RMI服務必須是在一個服務器中運行的。CalculatorServer類是一個非常簡單的服務器。
1. //CalculatorServer.java
2. import java.rmi.Naming;
3.
4. public class CalculatorServer {
5.
6. public CalculatorServer() {
7. try {
8. Calculator c = new CalculatorImpl();
9. Naming.rebind("rmi://localhost:1099/CalculatorService", c);
10. } catch (Exception e) {
11. System.out.println("Trouble: " + e);
12. }
13. }
14.
15. public static void main(String args[]) {
16. new CalculatorServer();
17. }
18. }
建立這個服務器程序,然后保存到你的目錄下,并且編譯它。
5、客戶端
客戶端源代碼如下:
//CalculatorClient.java
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
public class CalculatorClient {
public static void main(String[] args) {
try {
Calculator c = (Calculator)
Naming.lookup(
"rmi://localhost
/CalculatorService");
System.out.println( c.sub(4, 3) );
System.out.println( c.add(4, 5) );
System.out.println( c.mul(3, 6) );
System.out.println( c.div(9, 3) );
}
catch (MalformedURLException murle) {
System.out.println();
System.out.println(
"MalformedURLException");
System.out.println(murle);
}
catch (RemoteException re) {
System.out.println();
System.out.println(
"RemoteException");
System.out.println(re);
}
catch (NotBoundException nbe) {
System.out.println();
System.out.println(
"NotBoundException");
System.out.println(nbe);
}
catch (
java.lang.ArithmeticException
ae) {
System.out.println();
System.out.println(
"java.lang.ArithmeticException");
System.out.println(ae);
}
}
}
保存這個客戶端程序到你的目錄下(注意這個目錄是一開始建立那個,所有的我們的文件都在那個目錄下),并且編譯他。
6、運行RMI系統(tǒng)
現(xiàn)在我們建立了所有運行這個簡單RMI系統(tǒng)所需的文件,現(xiàn)在我們終于可以運行這個RMI系統(tǒng)啦!來享受吧。
我們是在命令控制臺下運行這個系統(tǒng)的,你必須開啟三個控制臺窗口,一個運行服務器,一個運行客戶端,還有一個運行RMIRegistry。
首先運行注冊程序RMIRegistry,你必須在包含你剛寫的類的那么目錄下運行這個注冊程序。
>rmiregistry
好,這個命令成功的話,注冊程序已經開始運行了,不要管他,現(xiàn)在切換到另外一個控制臺,在第二個控制臺里,我們運行服務器CalculatorService,因為RMI的安全機制將在服務端發(fā)生作用,所以你必須增加一條安全策略。以下是對應安全策略的例子
grant {
permission java.security.AllPermission "", "";
};
注意:這是一條最簡單的安全策略,它允許任何人做任何事,對于你的更加關鍵性的應用,你必須指定更加詳細安全策略。
現(xiàn)在為了運行服務端,你需要除客戶類(CalculatorClient.class)之外的所有的類文件。確認安全策略在policy.txt文件之后,使用如下命令來運行服務器。
> java -Djava.security.policy=policy.txt CalculatorServer
這個服務器就開始工作了,把接口的實現(xiàn)加載到內存等待客戶端的聯(lián)接。好現(xiàn)在切換到第三個控制臺,啟動我們的客戶端。
為了在其他的機器運行客戶端程序你需要一個遠程接口(Calculator.class) 和一個stub(CalculatorImpl_Stub.class)。 使用如下命令運行客戶端
> java -Djava.security.policy=policy.txt CalculatorClient
如果所有的這些都成功運行,你應該看到下面的輸出:
1
9
18
3
如果你看到了上面的輸出,恭喜你,你成功了,你已經成功的創(chuàng)建了一個RMI系統(tǒng),并且使他正確工作了。即使你運行在同一個計算機上,RMI還是使用了你的網(wǎng)絡堆棧和TCP/IP去進行通訊,并且是運行在三個不同的Java虛擬機上。這已經是一個完整的RMI系統(tǒng)。
摘要: java語言里包含了許多對設計模式的直接支持,如command模式,agent模式,observer模式等。雖然java提供的對這些模式的支持很簡單,不能滿足比較復雜的應用。但在簡單的場景下,使用這些類往往能夠得到立桿見影的效果。所以,如果沒有什么特殊需求,還是最好利用java的這些類。
Observ...
閱讀全文
接口:空心圓+直線(唐老鴨類實現(xiàn)了‘講人話’);
依賴:虛線+箭頭(動物和空氣的關系);
關聯(lián):實線+箭頭(企鵝需要知道氣候才遷移);
聚合:空心四邊形+實線+箭頭(雁群和大雁的關系);
合成/組合:實心四邊形+實線+箭頭(鳥和翅膀的關系);
泛化/繼承:空心三角形+實線(動物和鳥的繼承關系);
實現(xiàn):空心三角形+虛線(實現(xiàn)大雁飛翔的接口);
UML類圖
-
-
1. 首先看“動物”矩形框,它代表一個類。該類圖分為三層,第一層顯示類的名稱,如果是抽象類就要用斜體顯示。第二層是類的特性,通常就是字段和屬性。第三層是類的操作,通常是方法和行為。
-
注意前面的符號,‘+’表示public, ‘—’ 表示private, ‘#’表示protected.
-
2. “飛翔”矩形框表示一個接口圖,它與類圖的區(qū)別主要是頂端有《interface》顯示,第一行是接口名稱,第二行是接口方法。接口還有另一種表示方法,俗稱棒棒糖表示法,就是唐老鴨類實現(xiàn)了“講人話”的接口。
-
-
interface IFly interface Ilanguage
{ {
void Fly(); void Speak();
} }
-
3. 動物,鳥,鴨,唐老鴨他們之間都是繼承的關系,繼承關系用空心三角形+實現(xiàn)來表示。
-
-
4.“大雁”實現(xiàn)了“飛翔”接口。實現(xiàn)接口用空心三角形+虛線來表示。(注:下面的圖中應為空心三角形)
-
-
class Bird:Animal class WideGoose:IFly
{ {
//繼承動物類 //實現(xiàn)飛翔接口
} }
-
5. 企鵝與氣候有很大的關系,企鵝需要“知道”氣候的變化,需要“了解”氣候規(guī)律。當一個類“知道”另一個類時,可以用關聯(lián)(association)關系。關聯(lián)關系用實線箭頭來表示。
-
-
-
class Penguin :Bird
{
private Climate climate;//在企鵝Penguin中,引用到氣候Climate對象
}
-
6. “大雁”和“雁群”這兩個類。大雁是群居動物,每只大雁都屬于一個雁群,一個雁群可以有多只大雁。所以它們之間就滿足聚合(Aggregation)關系。聚合表示一種弱的“擁有”關系,體現(xiàn)的是A對象可以包含B對象,但B對象不是A對象的一部分。聚合關系用空心的菱形+ 實線箭頭表示。
-
-
-
class WideGooseAggregate
{
private WideGoose[] arrayWideGoose;
//在雁群WideGooseAggregate類中,有大雁數(shù)組對象arrayWideGoose
}
-
7. “鳥”和“翅膀”這兩個類。鳥和翅膀似整體和部分的關系,并且翅膀和鳥的生命周期是相同的,在這里鳥和其翅膀就是合成關系。合成(composition)是一種強的“擁有”關系,體現(xiàn)了嚴格的部分和整體的關系,部分和整體的生命周期一樣。合成關系用實心的的菱形+實線箭頭來表示。另外,合成關系的連線兩端還有一個數(shù)字“1”和數(shù)字“2”,,這被稱為基數(shù)。表明這一端的類可以有幾個實例,很顯然,一個鳥應該有兩支翅膀。如果一個類可能有無數(shù)個實例,則就用“n”來表示。關聯(lián)關系,聚合關系也可以有基數(shù)的。
-
class Bird
{
private Wing wing;
public Bird()
{
wing=new Wing();
//在鳥Bird類中,初始化時,實例化翅膀Wing,它們之間同時生成
}
}
-
8. “動物”、“氧氣”與“水”之間。動物有幾大特征,比如有新陳代謝,能繁殖。而動物要有生命,需要氧氣,水以及食物等。也就是說動物依賴于氧氣和水。它們之間是依賴關系(Dependency),用虛線箭頭來表示。
-
-
-
-
abstract class Animal
{
public bolism(Oxygen oxygen,Water water)
{
}
}
在manifest文件里->activity 添加
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*">
</intent-filter>
這樣就把當前程序注冊為 可以打開/查看所有類型的文件. 或者要查看jpeg, mimeType要改為: image/jpeg
當在文件管理器里點擊任何文件, 系統(tǒng)都會試圖去執(zhí)行你的程序.
轉自 http://chaozhong84.spaces.live.com/blog/cns!FC149E9A3FC0182B!297.trak
【Android】【轉】Android Log Analysis
---------------------------------------------------
本文原創(chuàng),轉載請注明出處,如有錯誤之處歡迎指出
---------------------------------------------------
Get Log from Android System
adb bugreport > bugreport.txt
copy bugreport to the current directory.
bugreport里面包含了各種log信息,大部分log也可以通過直接運行相關的程序來直接獲得.
步驟如下:
1.adb shell 2.進入相關工具程式的目錄 3.執(zhí)行相關程式 4.得到相關信息
下面以輸出進程信息為例 1.adb shell 2.輸入ps -P 3.可以看到相關進程信息
Log Archive Analysis
1.bugreport
bugreport記錄android啟動過程的log,以及啟動后的系統(tǒng)狀態(tài),包括進程列表,內存信息,VM信息等等到.
2.bugreport結構分析
(1)dumpstate
MEMORY INFO
獲取該log:讀取文件/proc/meminfo
系統(tǒng)內存使用狀態(tài)
CPU INFO
獲取該log:執(zhí)行/system/bin/top -n 1 -d 1 -m 30 -t
系統(tǒng)CPU使用狀態(tài)
PROCRANK
獲取該log:執(zhí)行/system/bin/procrank
執(zhí)行/system/xbin/procrank后輸出的結果,查看一些內存使用狀態(tài)
VIRTUAL MEMORY STATS
獲取該log:讀取文件/proc/vmstat
虛擬內存分配情況
vmalloc申請的內存則位于vmalloc_start~vmalloc_end之間,與物理地址沒有簡單的轉換關系,雖然在邏輯上它們也是連續(xù)的,但是在物理上它們不要求連續(xù)。
VMALLOC INFO
獲取該log:讀取文件/proc/vmallocinfo
虛擬內存分配情況
SLAB INFO
獲取該log:讀取文件/proc/slabinfo
SLAB是一種內存分配器.這里輸出該分配器的一些信息
ZONEINFO
獲取該log:讀取文件/proc/zoneinfo
zone info
SYSTEM LOG(需要著重分析)
獲取該log:執(zhí)行/system/bin/logcat -v time -d *:v
會輸出在程序中輸出的Log,用于分析系統(tǒng)的當前狀態(tài)
VM TRACES
獲取該log:讀取文件/data/anr/traces.txt
因為每個程序都是在各自的VM中運行的,這個Log是現(xiàn)實各自VM的一些traces
EVENT LOG TAGS
獲取該log:讀取文件/etc/event-log-tags
EVENT LOG
獲取該log:執(zhí)行/system/bin/logcat -b events -v time -d *:v
輸出一些Event的log
RADIO LOG
獲取該log:執(zhí)行/system/bin/logcat -b radio -v time -d *:v
顯示一些無線設備的鏈接狀態(tài),如GSM,PHONE,STK(Satellite Tool Kit)...
NETWORK STATE
獲取該log:執(zhí)行/system/bin/netcfg (得到網(wǎng)絡鏈接狀態(tài))
獲取該log:讀取文件/proc/net/route (得到路由狀態(tài))
顯示網(wǎng)絡鏈接和路由
SYSTEM PROPERTIES
獲取該log:參考代碼實現(xiàn)
顯示一些系統(tǒng)屬性,如Version,Services,network...
KERNEL LOG
獲取該log:執(zhí)行/system/bin/dmesg
顯示Android內核輸出的Log
KERNEL WAKELOCKS
獲取該log:讀取文件/proc/wakelocks
內核對一些程式和服務喚醒和休眠的一些記錄
KERNEL CPUFREQ
(Linux kernel CPUfreq subsystem) Clock scaling allows you to change the clock speed of the CPUs on the fly.
This is a nice method to save battery power, because the lower the clock speed is, the less power the CPU consumes.
PROCESSES
獲取該log:執(zhí)行ps -P
顯示當前進程
PROCESSES AND THREADS
獲取該log:執(zhí)行ps -t -p -P
顯示當前進程和線程
LIBRANK
獲取該log:執(zhí)行/system/xbin/librank
剔除不必要的library
BINDER FAILED TRANSACTION LOG
獲取該log:讀取文件/proc/binder/failed_transaction_log
BINDER TRANSACTION LOG
獲取該log:讀取文件/proc/binder/transaction_log
BINDER TRANSACTIONS
獲取該log:讀取文件/proc/binder/transactions
BINDER STATS
獲取該log:讀取文件/proc/binder/stats
BINDER PROCESS STATE
獲取該log:讀取文件/proc/binder/proc/*
bind相關的一些狀態(tài)
FILESYSTEMS
獲取該log:執(zhí)行/system/bin/df
主要文件的一些容量使用狀態(tài)(cache,sqlite,dev...)
PACKAGE SETTINGS
獲取該log:讀取文件/data/system/packages.xml
系統(tǒng)中package的一些狀態(tài)(訪問權限,路徑...),類似Windows里面的一些lnk文件吧.
PACKAGE UID ERRORS
獲取該log:讀取文件/data/system/uiderrors.txt
錯誤信息
KERNEL LAST KMSG LOG
最新kernel message log
LAST RADIO LOG
最新radio log
KERNEL PANIC CONSOLE LOG
KERNEL PANIC THREADS LOG
控制臺/線程的一些錯誤信息log
BACKLIGHTS
獲取該log:獲取LCD brightness讀/sys/class/leds/lcd-backlight/brightness
獲取該log:獲取Button brightness讀/sys/class/leds/button-backlight/brightness
獲取該log:獲取Keyboard brightness讀/sys/class/leds/keyboard-backlight/brightness
獲取該log:獲取ALS mode讀/sys/class/leds/lcd-backlight/als
獲取該log:獲取LCD driver registers讀/sys/class/leds/lcd-backlight/registers
獲取相關亮度的一些信息
(2)build.prop
VERSION INFO輸出下列信息
當前時間
當前內核版本:可以讀取文件(/proc/version)獲得
顯示當前命令:可以讀取文件夾(/proc/cmdline)獲得
顯示系統(tǒng)build的一些屬性:可以讀取文件(/system/build.prop)獲得
輸出系統(tǒng)一些屬性
gsm.version.ril-impl
gsm.version.baseband
gsm.imei
gsm.sim.operator.numeric
gsm.operator.alpha
(3)dumpsys
執(zhí)行/system/bin/dumpsys后可以獲得這個log.
經常會發(fā)現(xiàn)該log輸出不完整,因為代碼里面要求該工具最多只執(zhí)行60ms,可能會導致log無法完全輸出來.
可以通過修改時間參數(shù)來保證log完全輸出.
信息:
Currently running services
DUMP OF SERVICE services-name(running)
Log Code Analysis
Site: ."frameworks"base"cmds"dumpstate"
相關Log程序的代碼可以從上面目錄獲取
Log Analysis Experience
分析步驟
1.查看一些版本信息
確認問題的系統(tǒng)環(huán)境
2.查看CPU/MEMORY的使用狀況
看是否有內存耗盡,CPU繁忙這樣的背景情況出現(xiàn).
3.分析traces
因為traces是系統(tǒng)出錯以后輸出的一些線程堆棧信息,可以很快定位到問題出在哪里.
4.分析SYSTEM LOG
系統(tǒng)Log詳細輸出各種log,可以找出相關log進行逐一分析
實例分析
下面分析我寫的一個測試例子,在OnCreate做一個死循環(huán),這樣主線程會被鎖住,在按下硬件的Back之后會出現(xiàn)ANR的錯誤.
在traces中發(fā)現(xiàn)該程序的堆棧信息如下:
----- pid 20597 at 2010-03-15 01:29:53 -----
Cmd line: com.android.test
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=N obj=0x2aac6240 self=0xbda8
| sysTid=20597 nice=0 sched=0/0 cgrp=default handle=1877232296
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1306)
at java.lang.Thread.sleep(Thread.java:1286)
at android.os.SystemClock.sleep(SystemClock.java:114)
at com.android.test.main.onCreate(main.java:20)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
at android.app.ActivityThread.access$2200(ActivityThread.java:119)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #2" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c260 self=0x143860
| sysTid=20601 nice=0 sched=0/0 cgrp=default handle=1211376
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c1a0 self=0x14c980
| sysTid=20600 nice=0 sched=0/0 cgrp=default handle=1207920
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=N obj=0x2fb7a1e8 self=0x126cc0
| sysTid=20599 nice=0 sched=0/0 cgrp=default handle=1269048
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=N obj=0x2e31daf0 self=0x135c08
| sysTid=20598 nice=0 sched=0/0 cgrp=default handle=1268528
at dalvik.system.NativeStart.run(Native Method)
----- end 20597 -----
該文件的堆棧結構從下往上進行分析
(1)棧底at dalvik.system.NativeStart.run(Native Method)
系統(tǒng)為當前的task(應用程式)啟動一個專用的虛擬機
(2) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
Activity Services是在后臺負責管理Activity,它此時將測試例子的Activity啟動起來了
(3)at com.android.test.main.onCreate(main.java:20)
啟動測試程序
(4)棧頂at java.lang.VMThread.sleep(Native Method)
線程被sleep掉了,所以無法響應用戶,出現(xiàn)ANR錯誤.
上面是對一個非常簡單的問題的分析.
如果遇到比較復雜的問題還需要詳細分析SYSTEM LOG.
1.比如網(wǎng)絡異常,要通過SYSTEM LOG里面輸出的網(wǎng)絡鏈接信息來判斷網(wǎng)絡狀態(tài)
2.數(shù)據(jù)傳輸,網(wǎng)絡鏈接等耗時的操作需要分析SYSTEM LOG里面ActivityManager的響應時間
轉自:http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx
http://hi.baidu.com/donghaozheng/blog/item/30a00d4f9fca873baec3ab69.html
在 android 的API中有提供 SystemClock.setCurrentTimeMillis()函數(shù)來修改系統(tǒng)時間,可惜無論你怎么調用這個函數(shù)都是沒用的,無論模擬器還是真機,在logcat中總會得到"Unable to open alarm driver: Permission denied ".這個函數(shù)需要root權限或者運行與系統(tǒng)進程中才可以用。
本來以為就沒有辦法在應用程序這一層改系統(tǒng)時間了,后來在網(wǎng)上搜了好久,知道這個目的還是可以達到的。
第一個方法簡單點,不過需要在Android系統(tǒng)源碼的環(huán)境下用make來編譯:
1. 在應用程序的AndroidManifest.xml中的manifest節(jié)點中加入android:sharedUserId="android.uid.system"這個屬性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform這一行
3. 使用mm命令來編譯,生成的apk就有修改系統(tǒng)時間的權限了。
第二個方法麻煩點,不過不用開虛擬機跑到源碼環(huán)境下用make來編譯:
1. 同上,加入android:sharedUserId="android.uid.system"這個屬性。
2. 使用eclipse編譯出apk文件,但是這個apk文件是不能用的。
3. 用壓縮軟件打開apk文件,刪掉META-INF目錄下的CERT.SF和CERT.RSA兩個文件。
4. 使用目標系統(tǒng)的platform密鑰來重新給apk文件簽名。這步比較麻煩,首先找到密鑰文件,在我的Android源碼目錄中的位置是"build\target\product\security",下面的platform.pk8和platform.x509.pem兩個文件。然后用Android提供的Signapk工具來簽名,signapk的源代碼是在"build\tools\signapk"下,用法為"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用絕對路徑防止找不到,也可以修改源代碼直接使用。
這樣最后得到的apk和第一個方法是一樣的。
最后解釋一下原理,首先加入android:sharedUserId="android.uid.system"這個屬性。通過Shared User id,擁有同一個User id的多個APK可以配置成運行在同一個進程中。那么把程序的UID配成android.uid.system,也就是要讓程序運行在系統(tǒng)進程中,這樣就有權限來修改系統(tǒng)時間了。
只是加入UID還不夠,如果這時候安裝APK的話發(fā)現(xiàn)無法安裝,提示簽名不符,原因是程序想要運行在系統(tǒng)進程中還要有目標系統(tǒng)的platform key,就是上面第二個方法提到的platform.pk8和platform.x509.pem兩個文件。用這兩個key簽名后apk才真正可以放入系統(tǒng)進程中。第一個方法中加入LOCAL_CERTIFICATE := platform其實就是用這兩個key來簽名。
這也有一個問題,就是這樣生成的程序只有在原始的Android系統(tǒng)或者是自己編譯的系統(tǒng)中才可以用,因為這樣的系統(tǒng)才可以拿到platform.pk8和platform.x509.pem兩個文件。要是別家公司做的Android上連安裝都安裝不了。試試原始的Android中的key來簽名,程序在模擬器上運行OK,不過放到G3上安裝直接提示"Package ... has no signatures that match those in shared user android.uid.system",這樣也是保護了系統(tǒng)的安全。
最最后還說下,這個android:sharedUserId屬性不只可以把apk放到系統(tǒng)進程中,也可以配置多個APK運行在一個進程中,這樣可以共享數(shù)據(jù),應該會很有用的。
博主補充:
signapk編譯結束后在 android目錄下/out/host/linux-x86/framework/signapk.jar
使用方法:java -jar signapk.jar platform.x509.pem platform.pk8 test.apk test_signed.apk
實踐證明,第二種方法不需要刪掉META-INF目錄下的CERT.SF和CERT.RSA兩個文件,直接signapk就可以。
|
(1) Looper類別用來為一個線程開啟一個消息循環(huán)。默認情況下Android中新誕生的線程是沒有開啟消息循環(huán)的。(主線程除外,主線程系統(tǒng)會自動為其創(chuàng)建Looper對象,開啟消息循環(huán))
Looper對象通過MessageQueue來存放消息和事件。一個線程只能有一個Looper,對應一個MessageQueue。
(2) 通常是通過Handler對象來與Looper交互的。Handler可看做是Looper的一個接口,用來向指定的Looper發(fā)送消息及定義處理方法。
默認情況下Handler會與其被定義時所在線程的Looper綁定,比如,在主線程中定義,其是與主線程的Looper綁定。
mainHandler = new Handler() 等價于new Handler(Looper.myLooper()).
Looper.myLooper():Return the Looper object associated with the current thread 獲取當前進程的looper對象。
還有一個類似的 Looper.getMainLooper() 用于獲取主線程的Looper對象。
(3) 在非主線程中直接new Handler() 會報如下的錯誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主線程中默認沒有創(chuàng)建Looper對象,需要先調用Looper.prepare()啟用Looper。
(4) Looper.loop(); 讓Looper開始工作,從消息隊列里取消息,處理消息。
注意:寫在Looper.loop()之后的代碼不會被執(zhí)行,這個函數(shù)內部應該是一個循環(huán),當調用mHandler.getLooper().quit()后,loop才會中止,其后的代碼才能得以運行。
(5) 基于以上知識,可實現(xiàn)主線程給子線程(非主線程)發(fā)送消息。
把下面例子中的mHandler聲明成類成員,在主線程通過mHandler發(fā)送消息即可。
(6) Android官方文檔中Looper的介紹:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation ofprepare() and loop() to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
px (pixels) 像素
dip (device independent pixels) 設備獨立像素
sp (scaled pixels - best for text size ) 放大像素,對文本大小最好
pt (points) 點
in (inches) 英寸
mm (millimeters) 毫米
很多網(wǎng)友可能發(fā)現(xiàn)在Android的layout文件中l(wèi)ayout_width或layout_height有時候可能會指定具體的單位,比如有時候為px、dip或者sp等等。下面android123把常見的單位做下簡單的介紹,比如說
px (pixels)像素 -- 一般我們HVGA代表320x480像素,這個用的比較多。
dip或dp (device independent pixels)設備獨立像素 -- 這個和設備硬件有關,一般我們?yōu)榱酥С諻VGA、HVGA和QVGA cwj推薦使用這個,不依賴像素。
sp (scaled pixels — best for text size)放大像素-- 主要處理字體的大小。
下面的幾個是不常用的,大家也知道這里android123就不再過多的贅述。
in (inches)英寸
mm (millimeters)毫米
pt (points)點
px像素如何轉為dip設備獨立像素
最近有網(wǎng)友問如何將px像素轉為dip獨立設備像素,由于Android的設備分辨率眾多,目前主流的為wvga,而很多老的設備為hvga甚至低 端的qvga,對于兼容性來說使用dip無非是比較方便的,由于他和分辨率無關和屏幕的密度大小有關,所以推薦使用,不過這里android123提示大 家,ophone os的手機對于dip的支持糟糕透了,顯示的結果會放大很多,同時黑色的主題會導致常規(guī)的黑色文字讓用戶無法分辨。
px= (int) (dip*density+0.5f) //這里android開發(fā)網(wǎng)提示大家很多網(wǎng)友獲取density的方法存在問題,從資源中獲取的是靜態(tài)定義的,一般為1.0對于HVGA是正好的,而對于wvga這樣的應該從WindowsManager中獲取,WVGA為1.5
QVGA HVGA WVGA區(qū)別
文章分類:移動開發(fā)
QVGA即"Quarter VGA"。顧名思義即VGA的四分之一尺寸,亦即在液晶屏幕(LCD)上輸出的分辨率是240×320像素。QVGA支持屏幕旋轉,可以開發(fā)出相應的程序,以顯示旋轉90°、180°、270°屏幕位置。由HandEra公司發(fā)布。多用于手持/移動設備。 需要說明的是有些媒體把QVGA屏幕當成與TFT和TFD等LCD材質相同的東西是錯誤的,QVGA屏幕的說法多見與日本的一些手機中,目前采用微軟Pocket PC操作系統(tǒng)的智能手機屏幕也大多是320×240像素的QVGA屏幕。 所謂QVGA液晶技術,就是在液晶屏幕上輸出的分辨率是240×320的液晶輸出方式。這個分辨率其實和屏幕本身的大小并沒有關系。比如說,如果2.1英寸液晶顯示屏幕可以顯示240×320分辨率的圖像,就叫做“QVGA 2.1英寸液晶顯示屏”;如果3.8英寸液晶顯示屏幕可以顯示240×320的圖像,就叫做“QVGA 3.8英寸液晶顯示屏”,以上兩種情況雖然具有相同的分辨率,但是由于尺寸的不同實際的視覺效果也不同,一般 HVGA 即VGA(640*480)的一半,分辨率為(480*320),(3:2寬高比) 它是用于各種各樣的PDA設備,首先是2002年的索尼Clie PEG - NR70, 來說屏幕小的一個畫面自然也會細膩一些。 WVGA 數(shù)碼產品屏幕材質的一種,VGA的另一種形式,比VGA分辨率高,別名 : Wide VGA, ,其分辯率為800×480象素。是擴大了VGA(640×480)的分辨率。應用于PDA和手機等,因為很多網(wǎng)頁的寬度都是800,所以WVGA的屏幕會更加適和于瀏覽網(wǎng)頁,可以說是未來手持設備的分辨率的大趨勢