java frame linux_JAVA环境(下) - Android框架简介_Linux编程_Linux公社-Linux系统门户网站...

上节讲到了JAVA框架代码和应用程序的关系,那么框架代码和驱动层是怎么联系的呢?这就是这一节的内容:JNI

java使用一种叫做jni的技术来支持对C/C++代码的调用,在anroid中jni的代码放在froyo/frameworks/base/core/jni下,当然在java框架代码的目录下还有其他地方也多多少少放了jni代码,大家可以打开源码来看看。

整体关系如下图:

| java应用程序

--------------------------------------- Android系统api

| java框架

|本地接口声明

--------------------------------------

| JNI

--------------------------------------

| C/C++代码

继续拿来主义,C/C++中调试用printf,内核调试用printk,呵呵,android调试用log,那么我们就分析log的实现。

log的java代码froyo/frameworks/base/core/java/android/util/Log.java,

/*

* Copyright (C) 2006 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

*      http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

packageandroid.util;

importcom.android.internal.os.RuntimeInit;

importjava.io.PrintWriter;

importjava.io.StringWriter;

/**

* API for sending log output.

*

Generally, use the Log.v() Log.d() Log.i() Log.w() and Log.e()

* methods.

*

The order in terms of verbosity, from least to most is

* ERROR, WARN, INFO, DEBUG, VERBOSE.  Verbose should never be compiled

* into an application except during development.  Debug logs are compiled

* in but stripped at runtime.  Error, warning and info logs are always kept.

*

Tip: A good convention is to declare a TAG constant

* in your class:

*

private static final String TAG = "MyActivity";

*

* and use that in subsequent calls to the log methods.

*

Tip: Don't forget that when you make a call like

Log.v(TAG, "index=" + i);

* that when you're building the string to pass into Log.d, the compiler uses a

* StringBuilder and at least three allocations occur: the StringBuilder

* itself, the buffer, and the String object.  Realistically, there is also

* another buffer allocation and copy, and even more pressure on the gc.

* That means that if your log message is filtered out, you might be doing

* significant work and incurring significant overhead.

*/

publicfinalclassLog {

/**

* Priority constant for the println method; use Log.v.

*/

publicstaticfinalintVERBOSE =2;

/**

* Priority constant for the println method; use Log.d.

*/

publicstaticfinalintDEBUG =3;

/**

* Priority constant for the println method; use Log.i.

*/

publicstaticfinalintINFO =4;

/**

* Priority constant for the println method; use Log.w.

*/

publicstaticfinalintWARN =5;

/**

* Priority constant for the println method; use Log.e.

*/

publicstaticfinalintERROR =6;

/**

* Priority constant for the println method.

*/

publicstaticfinalintASSERT =7;

/**

* Exception class used to capture a stack trace in {@link #wtf()}.

*/

privatestaticclassTerribleFailureextendsException {

TerribleFailure(String msg, Throwable cause) {super(msg, cause); }

}

privateLog() {

}

/**

* Send a {@link #VERBOSE} log message.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

*/

publicstaticintv(String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, VERBOSE, tag, msg);

}

/**

* Send a {@link #VERBOSE} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @param tr An exception to log

*/

publicstaticintv(String tag, String msg, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, VERBOSE, tag, msg +'/n'+ getStackTraceString(tr));

}

/**

* Send a {@link #DEBUG} log message.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

*/

publicstaticintd(String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, DEBUG, tag, msg);

}

/**

* Send a {@link #DEBUG} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @param tr An exception to log

*/

publicstaticintd(String tag, String msg, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, DEBUG, tag, msg +'/n'+ getStackTraceString(tr));

}

/**

* Send an {@link #INFO} log message.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

*/

publicstaticinti(String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, INFO, tag, msg);

}

/**

* Send a {@link #INFO} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @param tr An exception to log

*/

publicstaticinti(String tag, String msg, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, INFO, tag, msg +'/n'+ getStackTraceString(tr));

}

/**

* Send a {@link #WARN} log message.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

*/

publicstaticintw(String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, WARN, tag, msg);

}

/**

* Send a {@link #WARN} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @param tr An exception to log

*/

publicstaticintw(String tag, String msg, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, WARN, tag, msg +'/n'+ getStackTraceString(tr));

}

/**

* Checks to see whether or not a log for the specified tag is loggable at the specified level.

*

*  The default level of any tag is set to INFO. This means that any level above and including

*  INFO will be logged. Before you make any calls to a logging method you should check to see

*  if your tag should be logged. You can change the default level by setting a system property:

*      'setprop log.tag. '

*  Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will

*  turn off all logging for your tag. You can also create a local.prop file that with the

*  following in it:

*      'log.tag.='

*  and place that in /data/local.prop.

*

* @param tag The tag to check.

* @param level The level to check.

* @return Whether or not that this is allowed to be logged.

* @throws IllegalArgumentException is thrown if the tag.length() > 23.

*/

publicstaticnativebooleanisLoggable(String tag,intlevel);

/*

* Send a {@link #WARN} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param tr An exception to log

*/

publicstaticintw(String tag, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, WARN, tag, getStackTraceString(tr));

}

/**

* Send an {@link #ERROR} log message.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

*/

publicstaticinte(String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, ERROR, tag, msg);

}

/**

* Send a {@link #ERROR} log message and log the exception.

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @param tr An exception to log

*/

publicstaticinte(String tag, String msg, Throwable tr) {

returnprintln_native(LOG_ID_MAIN, ERROR, tag, msg +'/n'+ getStackTraceString(tr));

}

/**

* What a Terrible Failure: Report a condition that should never happen.

* The error will always be logged at level ASSERT with the call stack.

* Depending on system configuration, a report may be added to the

* {@link android.os.DropBoxManager} and/or the process may be terminated

* immediately with an error dialog.

* @param tag Used to identify the source of a log message.

* @param msg The message you would like logged.

*/

publicstaticintwtf(String tag, String msg) {

returnwtf(tag, msg,null);

}

/**

* What a Terrible Failure: Report an exception that should never happen.

* Similar to {@link #wtf(String, String)}, with an exception to log.

* @param tag Used to identify the source of a log message.

* @param tr An exception to log.

*/

publicstaticintwtf(String tag, Throwable tr) {

returnwtf(tag, tr.getMessage(), tr);

}

/**

* What a Terrible Failure: Report an exception that should never happen.

* Similar to {@link #wtf(String, Throwable)}, with a message as well.

* @param tag Used to identify the source of a log message.

* @param msg The message you would like logged.

* @param tr An exception to log.  May be null.

*/

publicstaticintwtf(String tag, String msg, Throwable tr) {

tr =newTerribleFailure(msg, tr);

intbytes = println_native(LOG_ID_MAIN, ASSERT, tag, getStackTraceString(tr));

RuntimeInit.wtf(tag, tr);

returnbytes;

}

/**

* Handy function to get a loggable stack trace from a Throwable

* @param tr An exception to log

*/

publicstaticString getStackTraceString(Throwable tr) {

if(tr ==null) {

return"";

}

StringWriter sw =newStringWriter();

PrintWriter pw =newPrintWriter(sw);

tr.printStackTrace(pw);

returnsw.toString();

}

/**

* Low-level logging call.

* @param priority The priority/type of this log message

* @param tag Used to identify the source of a log message.  It usually identifies

*        the class or activity where the log call occurs.

* @param msg The message you would like logged.

* @return The number of bytes written.

*/

publicstaticintprintln(intpriority, String tag, String msg) {

returnprintln_native(LOG_ID_MAIN, priority, tag, msg);

}

/** @hide */publicstaticfinalintLOG_ID_MAIN =0;

/** @hide */publicstaticfinalintLOG_ID_RADIO =1;

/** @hide */publicstaticfinalintLOG_ID_EVENTS =2;

/** @hide */publicstaticfinalintLOG_ID_SYSTEM =3;

/** @hide */publicstaticnativeintprintln_native(intbufID,

intpriority, String tag, String msg);

}

我们看到所有代码都是调用public static native int println_native(int bufID,

int priority, String tag, String msg);来实现输出的,这个函数的实现就是C++,调用的方式就是JNI

我们看一下对应的jni代码froyo/frameworks/base/core/jni/android_util_Log.cpp,最终调用的输出函数是

/*

* In class android.util.Log:

*  public static native int println_native(int buffer, int priority, String tag, String msg)

*/

staticjint android_util_Log_println_native(JNIEnv* env, jobject clazz,

jint bufID, jint priority, jstring tagObj, jstring msgObj)

{

constchar* tag = NULL;

constchar* msg = NULL;

if(msgObj == NULL) {

jclass npeClazz;

npeClazz = env->FindClass("java/lang/NullPointerException");

assert(npeClazz != NULL);

env->ThrowNew(npeClazz,"println needs a message");

return-1;

}

if(bufID <0|| bufID >= LOG_ID_MAX) {

jclass npeClazz;

npeClazz = env->FindClass("java/lang/NullPointerException");

assert(npeClazz != NULL);

env->ThrowNew(npeClazz,"bad bufID");

return-1;

}

if(tagObj != NULL)

tag = env->GetStringUTFChars(tagObj, NULL);

msg = env->GetStringUTFChars(msgObj, NULL);

intres = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);

if(tag != NULL)

env->ReleaseStringUTFChars(tagObj, tag);

env->ReleaseStringUTFChars(msgObj, msg);

returnres;

}

当然我们发现最终输出是

intres = __android_log_buf_write(bufID, (android_LogPriority)priority, tag, msg);

用力grep了一下代码,结果如下

./system/core/include/cutils/log.h:int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);

./system/core/liblog/logd_write.c:int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)

./system/core/liblog/logd_write.c:    return __android_log_buf_write(bufID, prio, tag, buf);

这个就是和android专用驱动进行通信的方式,这个分析下去就有点深了,后面分析。

以上三个小节分析了android的JAVA环境,我这里都是简单的抛砖引玉,希望能给大家一点大体的指引,其他修行靠大家了,能成为是一个android程序员是多么幸福的事情,各位已经在幸福中了,我什么时候也可以幸福一把??0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值