Если быть точным, сборщики мусора являются проблемой для систем реального времени. Чтобы быть еще более точным, можно писать программное обеспечение в реальном времени на языках, которые имеют автоматическое управление памятью.
Более подробную информацию можно найти в Спецификации реального времени для Java об одном из подходов для достижения поведения в реальном времени с использованием Java. Идея RTSJ очень проста - не использовать кучу. RTSJ предоставляет новые разновидности объектов Runnable, которые гарантируют, что потоки не получат доступ к памяти кучи любого вида. Потоки могут получать доступ к памяти с областью действия (ничего необычного; значения уничтожаются при закрытии области действия) или к бессмертной памяти (которая существует в течение всего времени жизни приложения). Переменные в бессмертной памяти записываются снова и снова с новыми значениями.
Благодаря использованию бессмертной памяти RTSJ гарантирует, что потоки не обращаются к куче, и что более важно, система не имеет сборщика мусора, который препятствует выполнению программы потоками.
Более подробная информация доступна в статье «Проект Золотые Ворота: на пути к Java в реальном времени в космических полетах», опубликованной JPL и Sun .
Это сложная тема с множеством возможных решений и множеством плюсов и минусов для каждого. Есть замечательная статья здесь , в которой описаны несколько различных способов создания копии на C #. Подводя итог:
Клонировать вручную
Утомительный, но высокий уровень контроля.
Клонирование с помощью MemberwiseClone
Создает только поверхностную копию, т.е. для полей ссылочного типа исходный объект и его клон относятся к одному и тому же объекту.
Клонировать с отражением
По умолчанию неглубокая копия, может быть переписана для создания глубокой копии. Преимущество: автоматизированный. Недостаток: медленное отражение.
Клонирование с сериализацией
Легко, автоматизировано. Откажитесь от некоторого контроля, и сериализация будет медленнее всего.
Клонирование с использованием IL, клонирование с использованием методов расширения
Более продвинутые решения, не такие распространенные.
Это способ сделать это с помощью динамической генерации IL. Я нашел его где-то в Интернете:
public static class Cloner
{
static Dictionary<Type, Delegate> _cachedIL = new Dictionary<Type, Delegate>();
public static T Clone<T>(T myObject)
{
Delegate myExec = null;
if (!_cachedIL.TryGetValue(typeof(T), out myExec))
{
var dymMethod = new DynamicMethod("DoClone", typeof(T), new Type[] { typeof(T) }, true);
var cInfo = myObject.GetType().GetConstructor(new Type[] { });
var generator = dymMethod.GetILGenerator();
var lbf = generator.DeclareLocal(typeof(T));
generator.Emit(OpCodes.Newobj, cInfo);
generator.Emit(OpCodes.Stloc_0);
foreach (var field in myObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
// Load the new object on the eval stack... (currently 1 item on eval stack)
generator.Emit(OpCodes.Ldloc_0);
// Load initial object (parameter) (currently 2 items on eval stack)
generator.Emit(OpCodes.Ldarg_0);
// Replace value by field value (still currently 2 items on eval stack)
generator.Emit(OpCodes.Ldfld, field);
// Store the value of the top on the eval stack into the object underneath that value on the value stack.
// (0 items on eval stack)
generator.Emit(OpCodes.Stfld, field);
}
// Load new constructed obj on eval stack -> 1 item on stack
generator.Emit(OpCodes.Ldloc_0);
// Return constructed object. --> 0 items on stack
generator.Emit(OpCodes.Ret);
myExec = dymMethod.CreateDelegate(typeof(Func<T, T>));
_cachedIL.Add(typeof(T), myExec);
}
return ((Func<T, T>)myExec)(myObject);
}
}
MemberwiseClone требует меньшего обслуживания. Я не знаю, помогает ли какое-либо значение свойств по умолчанию, возможно, если бы можно было игнорировать элементы со значениями по умолчанию.
Я запуталась. MemberwiseClone ()
должен аннигилировать производительность чего-либо еще для неглубокой копии. В CLI любой тип, отличный от RCW, должен иметь возможность поверхностного копирования с помощью следующей последовательности:
memcpy
данные из оригинала в новый . Поскольку цель находится в питомнике, никаких барьеров записи не требуется. SuppressFinalize
, и такой флаг хранится в заголовке объекта, снимите его в клоне. Может ли кто-нибудь из команды разработчиков CLR объяснить, почему это не так. случай?