Почему передача статической ссылки на класс потребляет память?

снимок экрана инструментов

Мне трудно понять, почему это потребляет память.

Я пытался;

  1. Предоставление больше времени для очистки ARC
  2. Создание __weak копии глобальных переменных для передачи
  3. Посмотрел на использование __bridge или __bridge_transfer, но я не считаю, что это уместно.
  4. Делать глобальные переменные общедоступными и ссылаться на них напрямую (работает, но нецелесообразно)

Этот поток iOS Objective c переведен через j2objc 0.9.3 из приложения Java.

@implementation Comms_StatusThread

- (void)run {
while (true) {

    // Consumes memeory at aproximately 100k per 5 min
    [S globals];

    @try {
        [JavaLangThread sleepWithLong:10];
    }
    @catch (JavaLangInterruptedException *e) {
    }
}

Этот переведенный статический синглтон хранит «глобальные значения», к которым можно получить доступ из любого места в приложении (реальный код хранит гораздо больше классов и обратных вызовов).

@implementation S

Globals * S_globals__ = nil;

+ (Globals *)globals {
    {
        if (S_globals__ == nil) S_globals__ = [[Globals alloc] init];
        return S_globals__;
    }
}

@end

Любая помощь приветствуется. Я новичок в Objective-C и ARC. Я много читал об ARC, но до сих пор не понимаю причину такого потребления памяти.


Благодаря Student T я попробовал следующее.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(test:) userInfo:nil repeats:YES];
    return YES;
}

-(void) test: (NSObject*) o {
    [S comms];
    [S globals];
}

Это не потребляет памяти, и я планировал сделать это, однако новый ответ tball (используйте j2objc @AutoreleasePool), безусловно, лучший вариант, поэтому я начну с него.

Большое спасибо за все ваши ответы!


person Lorne K    schedule 29.08.2014    source источник
comment
Предоставление больше времени для очистки ARC Я не думаю, что ARC работает так, как вы думаете. ARC просто вставляет релиз во время компиляции. это не похоже на Java, где есть сборщик мусора, который сканирует и удаляет вещи.   -  person Brad Allred    schedule 29.08.2014


Ответы (3)


Предполагая, что вы компилируете с использованием ARC, иначе все преобразование бессмысленно. Ваш эксперимент не сработает, потому что вы поместите код в бесконечный цикл. Вы пытались приостановить поток, но это не сработало, потому что вы одновременно останавливали основной запущенный поток. Вам нужно дать основному циклу запуска возможность работать в течение 10 секунд.

person SmallChess    schedule 29.08.2014

S_globals не является статическим; в нем явно отсутствует ключевое слово статического модификатора. Таким образом, вы создаете новый каждый раз, когда зацикливаетесь, что происходит постоянно.

Откровенно говоря, этот код ужасен. Сделайте всем одолжение и не используйте переводчик Java.

person Jon Shier    schedule 29.08.2014
comment
Не совсем. Если он использует ARC, что я предполагаю (потому что он так сказал), это не будет проблемой. - person SmallChess; 29.08.2014
comment
Кроме того, пометка как статическая на самом деле просто означает, что переменная не может быть доступна за пределами исходного кода. - person SmallChess; 29.08.2014
comment
В долгосрочной перспективе утечки не будет, но поскольку код находится в жестком бесконечном цикле, у ARC нет шансов сделать свое дело. JShier прав, код ужасен, и ОП потратит больше времени на выяснение того, почему что-то не работает, чем на то, чтобы правильно написать его в ObjC. - person Paulw11; 29.08.2014
comment
Вероятно, ARC ожидает окончания цикла, чтобы освободить память. Поскольку это никогда не заканчивается, память никогда не освобождается. - person Jon Shier; 29.08.2014
comment
И это не то, что означает статика, Студент Т. - person Jon Shier; 29.08.2014
comment
Извините, я не показал файл .h, который указывает, что глобальные переменные являются статическими. Я проверил на «создание нового каждый раз», и это не было проблемой. - person Lorne K; 29.08.2014

Если необходимо написать цикл, постоянно создающий объекты, память будет увеличиваться независимо от того, используется ARC или нет. «A» в ARC означает «автоматический», поскольку его цель — автоматизировать использование методов сохранения/освобождения/автоматического освобождения. Эти методы не исчезают с ARC, они просто обрабатываются компилятором, а не разработчиком.

То, что j2objc добавило для долгоживущих объектов (таких как исполнители пула потоков, средства запуска модульных тестов и эталонные тесты), — это AutoreleasePool, которая (неудивительно) генерирует "@autoreleasepool { ... }". Эту аннотацию можно использовать в методах и для объявлений переменных цикла (ни в одном другом месте в Java 7, поскольку аннотации требуют объявлений, но мы сможем улучшить поддержку в Java 8). Поскольку создание и опустошение пула авторелиза отрицательно скажется на производительности, выберите рабочий «фрагмент» разумного размера, например следующий пример:

public void run() { while (true) { for (@AutoreleasePool int i = 0; i < 10000; i++) { S.globals(); } } }

Вы должны иметь возможность запускать это столько, сколько душе угодно, без нехватки памяти.

person tball    schedule 29.08.2014
comment
@Lorne K: j2objc используется в классе? Если да, мы будем рады узнать о вашем опыте по адресу [email protected]. - person tball; 29.08.2014
comment
Вау - это фантастика. Я явно должен был более тщательно изучить сайт j2objc перед публикацией. Это не для школы - мы 18-месячный стартап. В первую очередь аппаратное обеспечение, но у меня есть около 14000 строк кода Android, который очень хорошо переведен на Mac и iOS. Действительно спасает жизнь, поскольку аппаратное обеспечение сложное — несколько протоколов, типов шифрования, режимов подключения, типов данных и т. д. Если функция работает в Android, переводы iOS/Mac всегда работают идеально. У нас никогда не было проблем (только проблема с памятью). Также приятно разгрузить этот материал, чтобы я мог заняться прошивкой :) - person Lorne K; 30.08.2014