我一直在寻找一些时间用于描述Dalvik VM垃圾收集器架构的详细设计文档,但是没有发现太多.考虑到GC运行的性能影响,我真的希望更好地理解5个具体问题:1.究竟是什么触发了Android中的GC?我见过的其他VM实现通常允许在GC收到运行信号之前将一定比例的系统内存分配给应用程序.然而,扫描以下LogCat似乎表明Dalvik GC至少部分运行 -
12-14 11:34:57.753: D/dalvikvm(279): GC_EXTERNAL_ALLOC freed 735 objects / 54272 bytes
in 90ms
12-14 11:34:57.893: D/dalvikvm(279): GC_EXTERNAL_ALLOC freed 256 objects / 12240 bytes
in 61ms
12-14 11:34:57.943: I/jPCT-AE(279): Loading Texture...
12-14 11:34:57.993: D/dalvikvm(279): GC_FOR_MALLOC freed 65 objects / 2840 bytes in
52ms
12-14 11:34:58.013: I/dalvikvm-heap(279): Grow heap (frag case) to 5.039MB for
1048592-byte allocation
12-14 11:34:58.073: D/dalvikvm(279): GC_FOR_MALLOC freed 1 objects / 40 bytes in 59ms
12-14 11:34:58.243: D/dalvikvm(279): GC_EXTERNAL_ALLOC freed 11 objects / 432 bytes in …Run Code Online (Sandbox Code Playgroud) 催化剂
我将Android Studio升级到2.3,将Gradle插件升级到3.3
最初的问题
将Gradle插件更新为3.3后,我收到错误"错误:SDK Build Tools修订版(23.0.3)对于项目来说太低了':mymodulename'.最低要求是25.0.0"
我尝试将buildToolsVersion调整为25.0.2并将compileSdkVersion调整为25,以及所有com.android.support依赖项(因为它们的主要版本需要匹配compileSdkVersion).这个调整清除了这个问题,但后来我意识到我的应用程序还不支持Nougat所以我将compileSdkVersion减少到了我的targetSdkVersion 23.关于构建工具太低的错误信息仍然没有了,所以我觉得我很清楚.
第一个依赖错误
将compileSdkVersion击倒到23之后,我试图重建,并看到几个类似于"错误的错误:(3)错误检索项目的父项:找不到与给定名称匹配的资源'android:TextAppearance.Material.Widget.Button.Borderless.有色'".我意识到我忘记改变我的com.android.support依赖项,使得它们的主要版本再次与较低的compileSdkVersion匹配,所以我将它们降低到23.3.0
第二个依赖错误
在解决了第一个依赖性错误后,我能够再次编译并运行我的应用程序.但是,在我的第一个com.android.support依赖项下面仍然存在红色波形,错误说明"所有com.android.support库必须使用完全相同的版本规范(混合版本可能导致运行时崩溃).发现版本24.0 .0,23.3.0.例子包括com.android.support:support-v4:24.0.0和com.android.support:animated-vector-drawable:23.3.0"
我的build.gradle中没有任何内容专门引用24.0.0,看哪:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion '25.0.2'
defaultConfig {
applicationId ...
minSdkVersion 16
targetSdkVersion 23
versionCode ...
versionName ...
}
buildTypes {
debug{
debuggable true
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions{
//check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
dexOptions{
jumboMode true …Run Code Online (Sandbox Code Playgroud) 我正在构建一个相当简单的 Android 应用程序(sdk 修订版 14:ICS),它允许用户一次选择两个音频剪辑(都是 RIFF/WAV 格式、小端、有符号的 PCM-16 位编码)并将它们组合在一起创造新声音的各种方法。我用于这种组合的最基本方法如下:
//...sound samples are read in to memory as raw byte arrays elsewhere
//...offset is currently set to 45 so as to skip the 44 byte header of basic
//RIFF/WAV files
...
//Actual combination method
public byte[] makeChimeraAll(int offset){
for(int i=offset;i<bigData.length;i++){
if(i < littleData.length){
bigData[i] = (byte) (bigData[i] + littleData[i]);
}
else{
//leave bigData alone
}
}
return bigData;
}
Run Code Online (Sandbox Code Playgroud)
然后可以通过 AudioTrack 类播放返回的字节数组:
....
hMain.setBigData(hMain.getAudioTransmutation().getBigData()); //set the shared bigData
// to the …Run Code Online (Sandbox Code Playgroud) 我最近一直在使用 STL 的 unordered_map ,虽然它似乎工作得很好,但我不太明白散列函数是如何工作的,因为数据类型是作为模板参数给出的。为了更彻底地理解这个数据结构,我用 C++ 实现了我自己的小 Hashmap 类:
哈希表接口:
#ifndef _HASHMAP_H_
#define _HASHMAP_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <vector.h>
//Beginning of Hashmap class definition
template <class Key, class Value>
class Hashmap{
private:
int mappedElementCount;
public:
explicit Hashmap();
virtual ~Hashmap();
virtual void test();
virtual int hash(Key*);
int* getSize();
void putKVPair(Key*,Value*);
void clearMap();
//When we use these methods, we'll want a linear vector of keys and values to
//iterate over, so vector is good here
std::vector<Key>* getKeys(); …Run Code Online (Sandbox Code Playgroud) JDK 7 Java文档提出了以下两个用于创建Java线程的习惯用法:
扩展线程并覆盖run()
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
...
//And to launch the custom Thread
PrimeThread p = new PrimeThread(143);
p.start();
Run Code Online (Sandbox Code Playgroud)实现Runnable并创建一个新的Thread,将Runnable impl传递给它的构造函数
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
...
//And to …Run Code Online (Sandbox Code Playgroud)消息'what'字段对于Handler实例或一个或多个Handler实例可能与之关联的线程的MessageQueue是唯一的吗?该文档阅读"A处理器让您发送和处理信息和Runnable对象与线程的MessageQueue关联.每个处理程序实例与单个线程关联和线程的消息队列.当你创建一个新的处理程序,它被绑定到线程正在创建它的线程的/ message队列 - 从那时起,它将消息和runnables传递给该消息队列并在它们从消息队列中出来时执行它们"这似乎表明消息'什么'代码必须对于MessageQueue是唯一的,因此在单个线程的范围内而不是Handler的单个实例.
我的整个项目中有几个与我的UI线程相关联的Handler对象,所以我必须确保发送到这些处理程序中的所有Message"what"代码都是唯一的,或者它们只需要对每个Handler实例都是唯一的?
例如,在执行以下代码并收到两条消息后,日志会说什么:
class MainActivity extends Activity{
public static final String TAG = "MainActivity";
public static final int FIRST_PURPOSE_MESSAGE_CODE = 1;
public static final int SECOND_PURPOSE_MESSAGE_CODE = 1;
...
private static class FirstUIThreadHandler extends Handler{
...
@Override
public void handleMessage(Message msg){
switch(msg.what){
case FIRST_PURPOSE_MESSAGE_CODE:
Log.v(TAG,"handling the first message");
break;
}
}
}
...
private static class SecondUIThreadHandler extends Handler{
...
@Override
public void handleMessage(Message msg){
switch(msg.what){
case SECOND_PURPOSE_MESSAGE_CODE:
Log.v(TAG,"handling the second message");
break;
}
} …Run Code Online (Sandbox Code Playgroud) 可能重复:
为什么使用'new'导致内存泄漏?
我对STL很新,而且我已经读过,通常保持对象的向量而不是对象的指针向量是一种好习惯.为了遵守这个信条,我遇到了以下情况:
//Approach A
//dynamically allocates mem for DD_DungeonRoom object, returns a pointer to the block.
//then, presumably, copy-constructs the de-referenced DD_DungeonRoom as a
//disparate DD_DungeonRoom object to be stored at the tail of the vector
//Probably causes memory leak due to the dynamically allocated mem block not being
//caught and explicitly deleted
mvLayoutArray.push_back(*(new DD_DungeonRoom()));
//Approach B
//same as A, but implemented in such a way that the dynamically allocated mem block
//tempRoom can be deleted after it is …Run Code Online (Sandbox Code Playgroud) 从向量文档中可以看出,完全释放您具有类成员指针的值向量的正确方法如下所示:
std::vector<MyObject>* mvMyObjectVector_ptr;
...
//In the class constructor:
mvMyObjectVector_ptr = new std::vector<MyObject>();
Run Code Online (Sandbox Code Playgroud)
将按顺序在类的析构函数实现中调用以下内容
mvMyObjectVector_ptr->clear();
delete mvMyObjectVector_ptr;
Run Code Online (Sandbox Code Playgroud)
但是,这似乎导致SIGABRT'指针被释放未被分配'错误.上面的成语是完全释放保存在指向向量的指针所指向的地址的内存的正确方法(如果是,我认为我的错误来自其他东西)?如果没有,那么正确的方法是什么?