public override bool ProcessEvent(JvmtiEnvironment environment, JniEnvironment nativeEnvironment, EventProcessor processor, ThreadId thread, TaggedReferenceTypeId @class, Location? location)
            {
                if (!base.ProcessEvent(environment, nativeEnvironment, processor, thread, @class, location))
                    return false;

                // Step Out is implemented with Frame Pop events set at the correct depth
                if (_depth == StepDepth.Out)
                {
                    if (location.HasValue && !location.Value.Method.Equals(_lastMethod))
                    {
                        _lastLocation = new jlocation((long)location.Value.Index);
                        _lastMethod = location.Value.Method;
                        UpdateLastLine(environment);
                    }

                    return true;
                }

                using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread))
                {
                    int stackDepth;
                    JvmtiErrorHandler.ThrowOnFailure(environment.GetFrameCount(threadHandle.Value, out stackDepth));

                    if (_hasMethodInfo && stackDepth > _stackDepth)
                    {
                        bool convertToFramePop;
                        if (location.HasValue && (!_convertedToFramePop || !_framePopMethod.Equals(location.Value.Method)) && ShouldSkipCurrentMethod(processor.VirtualMachine, environment, nativeEnvironment, threadHandle.Value, stackDepth, location.Value, out convertToFramePop))
                        {
                            if (convertToFramePop)
                            {
                                // remove the single step event
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.FramePop, this.RequestId));
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.ClearEventInternal(EventKind.SingleStep, this.RequestId));
                                // set an actual step filter to respond when the thread arrives back in this frame
                                JvmtiErrorHandler.ThrowOnFailure((jvmtiError)processor.SetEventInternal(environment, nativeEnvironment, EventKind.FramePop, this));
                                _convertedToFramePop = true;
                                _framePopMethod = location.Value.Method;
                            }

                            return false;
                        }
                        else
                        {
                            _convertedToFramePop = false;
                            return true;
                        }
                    }
                    else if (stackDepth == _stackDepth)
                    {
                        if (_size == StepSize.Statement && _disassembledMethod != null)
                        {
                            int instructionIndex = _disassembledMethod.Instructions.FindIndex(i => (uint)i.Offset == location.Value.Index);
                            if (instructionIndex >= 0 && _evaluationStackDepths != null && (_evaluationStackDepths[instructionIndex] ?? 0) != 0)
                            {
                                return false;
                            }
                            else if (instructionIndex >= 0 && _disassembledMethod.Instructions[instructionIndex].OpCode.FlowControl == JavaFlowControl.Branch)
                            {
                                // follow branch instructions before stopping
                                return false;
                            }
                        }
                        else if (_lastLine != null)
                        {
                            // see if we're on the same line
                            LineNumberData[] lines;
                            jvmtiError error = environment.GetLineNumberTable(location.Value.Method, out lines);
                            if (error == jvmtiError.None)
                            {
                                LineNumberData entry = lines.LastOrDefault(i => i.LineCodeIndex <= (long)location.Value.Index);
                                if (entry.LineNumber == _lastLine)
                                    return false;
                            }
                        }
                    }

                    if (location.HasValue)
                    {
                        _lastLocation = new jlocation((long)location.Value.Index);
                        _lastMethod = location.Value.Method;
                        UpdateLastLine(environment);
                    }

                    _stackDepth = stackDepth;
                    return true;
                }
            }
            public StepEventFilter(EventKind internalEventKind, RequestId requestId, SuspendPolicy suspendPolicy, IEnumerable<EventRequestModifier> modifiers, ThreadId thread, JvmtiEnvironment environment, JniEnvironment nativeEnvironment, StepSize size, StepDepth depth)
                : base(internalEventKind, requestId, suspendPolicy, modifiers, thread)
            {
                if (size == StepSize.Statement && JavaVM.DisableStatementStepping)
                    size = StepSize.Line;

                _size = size;
                _depth = depth;

                // gather reference information for the thread
                using (var threadHandle = environment.VirtualMachine.GetLocalReferenceForThread(nativeEnvironment, thread))
                {
                    if (threadHandle.IsAlive)
                    {
                        jvmtiError error = environment.GetFrameLocation(threadHandle.Value, 0, out _lastMethod, out _lastLocation);
                        if (error == jvmtiError.None)
                            error = environment.GetFrameCount(threadHandle.Value, out _stackDepth);

                        if (error == jvmtiError.None)
                            _hasMethodInfo = true;

                        UpdateLastLine(environment);

                        if (error == jvmtiError.None && size == StepSize.Statement && (depth == StepDepth.Over || depth == StepDepth.Into))
                        {
                            byte[] bytecode;
                            JvmtiErrorHandler.ThrowOnFailure(environment.GetBytecodes(_lastMethod, out bytecode));
                            _disassembledMethod = BytecodeDisassembler.Disassemble(bytecode);

                            TaggedReferenceTypeId declaringClass;
                            JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodDeclaringClass(nativeEnvironment, _lastMethod, out declaringClass));
                            using (var classHandle = environment.VirtualMachine.GetLocalReferenceForClass(nativeEnvironment, declaringClass.TypeId))
                            {
                                int constantPoolCount;
                                byte[] data;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetConstantPool(classHandle.Value, out constantPoolCount, out data));

                                List<ConstantPoolEntry> entryList = new List<ConstantPoolEntry>();
                                int currentPosition = 0;
                                for (int i = 0; i < constantPoolCount - 1; i++)
                                {
                                    entryList.Add(ConstantPoolEntry.FromBytes(data, ref currentPosition));
                                    switch (entryList.Last().Type)
                                    {
                                    case ConstantType.Double:
                                    case ConstantType.Long:
                                        // these entries take 2 slots
                                        entryList.Add(ConstantPoolEntry.Reserved);
                                        i++;
                                        break;

                                    default:
                                        break;
                                    }
                                }

                                _constantPool = entryList.AsReadOnly();

                                string classSignature;
                                string classGenericSignature;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetClassSignature(classHandle.Value, out classSignature, out classGenericSignature));
                                string methodName;
                                string methodSignature;
                                string methodGenericSignature;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetMethodName(_lastMethod, out methodName, out methodSignature, out methodGenericSignature));

                                jobject classLoader;
                                JvmtiErrorHandler.ThrowOnFailure(environment.GetClassLoader(classHandle.Value, out classLoader));
                                long classLoaderTag;
                                JvmtiErrorHandler.ThrowOnFailure(environment.TagClassLoader(classLoader, out classLoaderTag));

                                ReadOnlyCollection<ExceptionTableEntry> exceptionTable;
                                JvmtiErrorHandler.ThrowOnFailure(environment.VirtualMachine.GetExceptionTable(classLoaderTag, classSignature, methodName, methodSignature, out exceptionTable));

                                _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, _constantPool, exceptionTable);
                            }
                        }
                    }
                }
            }