2011-02-02 1 views
0

SAX 사용 중에 Java에서 이상한 동작이 나타납니다. 값은 설정 중이지만 출력의 toString 메소드에서 기본값으로 되돌립니다. 이것은 정말로 이례적인 것 같습니다. 코드를 살펴보고 변수의 메모리 주소를 출력했습니다. 모든 것이 올바른 순서로 발생하고 겉으로보기에는 올바르게 완료되었습니다. deserialised 된 다른 XML 요소는 문제가 없으므로 해결할 수 없습니다.XML 디시리얼라이저의 이상한 동작

내 시스템은 다음과 같이 작동합니다. 사용자가 속성 도우미와 요소 처리기를 정의하는 추상 메소드가있는 클래스가 있습니다. 요소 핸들러는 하위 XML 요소를 기반으로 하위 클래스 생성을 처리하는 반면 특성 핸들러는 생성자에서 특성 목록을 가져 와서 속성 도우미를 통해 속성 도우미에서 구현 된 추상 메서드를 통해 필드를 설정하는 데 사용합니다.

package kokuks.flowmon; 

import kokuks.flowmon.FlowmonParser.Handler; 

import org.xml.sax.Attributes; 

public class FlowProbeFlowStats extends FlowmonParserElement { 
    protected final FlowProbe parent; 
    protected int flowId = 0; 
    protected int packets = 0; 
    protected int bytes = 0; 
    protected long delayFromFirstProbeSum = 0; 
    protected boolean set = false; 

    /** 
    * @param handler 
    * @param parent 
    * @param uri 
    * @param localName 
    * @param qName 
    * @param attributes 
    */ 
    FlowProbeFlowStats(Handler handler, FlowProbe parent, String uri, String localName, String qName, Attributes attributes) { 
     super(handler, parent, uri, localName, qName, attributes); 
     this.parent = parent; 
    } 

    /** 
    * @return the parent 
    */ 
    public FlowProbe getParent() { 
     return parent; 
    } 

    /* (non-Javadoc) 
    * @see kokuks.flowmon.FlowmonParserElement#getXMLName() 
    */ 
    @Override 
    protected String getXMLName() { 
     return "FlowStats"; 
    } 

    /* (non-Javadoc) 
    * @see kokuks.flowmon.FlowmonParserElement#createAttributeHandlers() 
    */ 
    @Override 
    protected IAttributeHandler[] createAttributeHandlers() { 
     return new IAttributeHandler[] { 
      new AttributeHandler("flowId") { 
       @Override 
       public void perform(String argValue) { 
        System.out.println("AH flowId: " + argValue); 
        flowId = Integer.parseInt(argValue); 
        set = true; 
       } 
      }, 
      new AttributeHandler("packets") { 
       @Override 
       public void perform(String argValue) { 
        System.out.println("AH packets: " + argValue); 
        packets = Integer.parseInt(argValue); 
        set = true; 
       } 
      }, 
      new AttributeHandler("bytes") { 
       @Override 
       public void perform(String argValue) { 
        System.out.println("AH bytes: " + argValue); 
        bytes = Integer.parseInt(argValue); 
        set = true; 
       } 
      }, 
      new AttributeHandler("delayFromFirstProbeSum") { 
       @Override 
       public void perform(String argValue) { 
        System.out.println("AH delayFromFirstProbeSum: " + argValue); 
        delayFromFirstProbeSum = Long.parseLong(argValue.substring(0, argValue.length() - 2)); 
        set = true; 
       } 
      } 
     }; 
    } 

    /* (non-Javadoc) 
    * @see java.lang.Object#toString() 
    */ 
    @Override 
    public String toString() { 
     return "FlowStats/" + super.toString() + "[flowId: " + flowId + ", packets: " + packets + 
     ", bytes: " + bytes + ", delayFromFirstProbeSum: " + delayFromFirstProbeSum + "]"; 
    } 
} 

나는 또한 속성이 조회됩니다 및 관련 구현 방법이라는 몇 가지 디버깅 출력이 :

여기에 문제의 문제가 클래스입니다.

if (this instanceof FlowProbeFlowStats) { 
     System.out.println("ahaaaa1:: " + this.toString()); 
    } 

    IAttributeHandler[] ahandlers = createAttributeHandlers(); 

    if (ahandlers != null) { 
     Map<String, IAttributeHandler> attributeHandlers = new HashMap<String, IAttributeHandler>(ahandlers.length); 
     for (IAttributeHandler ah : ahandlers) { 
      attributeHandlers.put(ah.getName(), ah); 
     } 

     for (int i = 0; i < attributes.getLength(); i++) { 
      IAttributeHandler ah = attributeHandlers.get(attributes.getQName(i)); 
      if (ah == null) { 
       throw new IllegalStateException("Attribute helper not found in qName: " + qName + " for attrib with localName: " + attributes.getLocalName(i) + ", qname*: " + attributes.getQName(i)); 
      } 

      try { 
       ah.perform(attributes.getValue(i)); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    if (this instanceof FlowProbeFlowStats) { 
     System.out.println("ahaaaa2:: " + this.toString()); 
    } 

어쨌든, 여기에 출력됩니다 :

ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 1 
AH packets: 5 
AH bytes: 333 
AH delayFromFirstProbeSum: 50274395ns 
ahaaaa2:: FlowStats/[email protected][flowId: 1, packets: 5, bytes: 333, delayFromFirstProbeSum: 50274395] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 2 
AH packets: 5 
AH bytes: 333 
AH delayFromFirstProbeSum: 50274395ns 
ahaaaa2:: FlowStats/[email protected][flowId: 2, packets: 5, bytes: 333, delayFromFirstProbeSum: 50274395] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 3 
AH packets: 5 
AH bytes: 1082 
AH delayFromFirstProbeSum: 0ns 
ahaaaa2:: FlowStats/[email protected][flowId: 3, packets: 5, bytes: 1082, delayFromFirstProbeSum: 0] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 4 
AH packets: 4 
AH bytes: 762 
AH delayFromFirstProbeSum: 0ns 
ahaaaa2:: FlowStats/[email protected][flowId: 4, packets: 4, bytes: 762, delayFromFirstProbeSum: 0] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 2 
AH packets: 5 
AH bytes: 333 
AH delayFromFirstProbeSum: 0ns 
ahaaaa2:: FlowStats/[email protected][flowId: 2, packets: 5, bytes: 333, delayFromFirstProbeSum: 0] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 4 
AH packets: 4 
AH bytes: 762 
AH delayFromFirstProbeSum: 40615996ns 
ahaaaa2:: FlowStats/[email protected][flowId: 4, packets: 4, bytes: 762, delayFromFirstProbeSum: 40615996] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 1 
AH packets: 5 
AH bytes: 333 
AH delayFromFirstProbeSum: 0ns 
ahaaaa2:: FlowStats/[email protected][flowId: 1, packets: 5, bytes: 333, delayFromFirstProbeSum: 0] 
ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
AH flowId: 3 
AH packets: 5 
AH bytes: 1082 
AH delayFromFirstProbeSum: 51335996ns 
ahaaaa2:: FlowStats/[email protected][flowId: 3, packets: 5, bytes: 1082, delayFromFirstProbeSum: 51335996] 
[kks-j~KokuKS~/Names] fmxml:FlowMonitor[FlowStats[Flow[flowID: 1,timeFirstTxPacket: 1011735011,timeLastTxPacket: 1343457103,timeFirstRxPacket: 1021768610,timeLastRxPacket: 1353490702,delaySum: 50274395,jitterSum: 212800,lastDelay: 10033599,txBytes: 333, rxBytes: 333,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0],Flow[flowID: 2,timeFirstTxPacket: 1015259481,timeLastTxPacket: 1543226881,timeFirstRxPacket: 1025293080,timeLastRxPacket: 1553260480,delaySum: 50274395,jitterSum: 212800,lastDelay: 10033599,txBytes: 333, rxBytes: 333,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0],Flow[flowID: 3,timeFirstTxPacket: 1021768610,timeLastTxPacket: 1332941904,timeFirstRxPacket: 1031802209,timeLastRxPacket: 1343457103,delaySum: 51335996,jitterSum: 481600,lastDelay: 10515199,txBytes: 1082, rxBytes: 1082,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0],Flow[flowID: 4,timeFirstTxPacket: 1025293080,timeLastTxPacket: 1332969282,timeFirstRxPacket: 1035326679,timeLastRxPacket: 1343226881,delaySum: 40615996,jitterSum: 291200,lastDelay: 10257599,txBytes: 762, rxBytes: 762,txPackets: 4,rxPackets: 4,lostPackets: 0,timesForwarded: 0]],Ipv4FlowClassifier[Flow[flowId: 4, sourceAddress: 10.1.0.1, destinationAddress: 10.1.0.2, protocol: 6],Flow[flowId: 3, sourceAddress: 10.1.0.1, destinationAddress: 10.1.1.2, protocol: 6],Flow[flowId: 2, sourceAddress: 10.1.0.2, destinationAddress: 10.1.0.1, protocol: 6],Flow[flowId: 1, sourceAddress: 10.1.1.2, destinationAddress: 10.1.0.1, protocol: 6]],FlowProbes[FlowProbe[index: 0, stats: <FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0],FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0],FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0],FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0]>],FlowProbe[index: 1, stats: <FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0],FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0]>],FlowProbe[index: 2, stats: <FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0],FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0]>]]] 

주 메모리 값 - 그것은 아주 기괴한입니다. 변환 된 루트 XML 요소의 전체 toString 출력이 마지막 행에 있습니다.

어쨌든, 어떤 도움을 주셔서 감사합니다,
크리스

편집 : 설정하는 동안 여기

protected final FlowProbe parent; 
protected int flowId = 1000; 
protected int packets = 1000; 
protected int bytes = 1000; 
protected long delayFromFirstProbeSum = 1000; 
protected boolean set = false; 

그리고 결과입니다 : 내가 몇 가지 다른 기본 변수의 값보다는 0을 설정

ahaaaa1:: FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 
[email protected]: AH flowId: 4 
[email protected]: AH packets: 5 
[email protected]: AH bytes: 1082 
[email protected]: AH delayFromFirstProbeSum: 0ns 
ahaaaa2:: FlowStats/[email protected][flowId: 4, packets: 5, bytes: 1082, delayFromFirstProbeSum: 0] 

처음에는 이상한 일이 발생하기 때문에 값은 1000이 아니라 0입니다. 매우 이상합니다. 최종 출력에 관해서는, 출력되는 오브젝트의 값은 0이 아닌 1000입니다 (필드 기본값의 초기 값).

Edit2가 : 나는 지금 헤더에 다음과 같습니다 속성이 설정되어있을 때 감소한다

protected int countdown = 4; 

. 예는 다음과 같습니다

 new AttributeHandler("packets") { 
      @Override 
      public void perform(String argValue) { 
       synchronized (FlowProbeFlowStats.this) { 
        System.out.println(FlowProbeFlowStats.super.toString() + ": AH packets: " + argValue); 
        packets = Integer.parseInt(argValue); 
        System.out.println("packets set to " + packets); 
        set = true; 
        countdown--; 
       } 
      } 
     }, 

oString 문은 지금 :

/* (non-Javadoc) 
* @see java.lang.Object#toString() 
*/ 
@Override 
public String toString() { 
    return "FlowStats/" + super.toString() + "[flowId: " + flowId + ", packets: " + packets + 
    ", bytes: " + bytes + ", delayFromFirstProbeSum: " + delayFromFirstProbeSum + 
    ", countdown: " + countdown + "]"; 
} 

및 인쇄 아웃 읽기 :

에게 속성 세터와 된 toString 동기화 된 문이 여기에 있었다
ahaaaa2:: FlowStats/[email protected][flowId: 1, packets: 5, bytes: 333, delayFromFirstProbeSum: 0, countdown: -4] 

... 

[kks-j~KokuKS~/Names] fmxml:FlowMonitor[FlowStats[Flow[flowID: 1,timeFirstTxPacket: 1007829288,timeLastTxPacket: 1524157706,timeFirstRxPacket: 1017862887,timeLastRxPacket: 1534191305,delaySum: 50274395,jitterSum: 212800,lastDelay: 10033599,txBytes: 333, rxBytes: 333,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0],Flow[flowID: 2,timeFirstTxPacket: 1010210025,timeLastTxPacket: 1324387511,timeFirstRxPacket: 1020243624,timeLastRxPacket: 1334421110,delaySum: 50274395,jitterSum: 212800,lastDelay: 10033599,txBytes: 333, rxBytes: 333,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0],Flow[flowID: 3,timeFirstTxPacket: 1017862887,timeLastTxPacket: 1313900107,timeFirstRxPacket: 1027896486,timeLastRxPacket: 1324157706,delaySum: 40615996,jitterSum: 291200,lastDelay: 10257599,txBytes: 762, rxBytes: 762,txPackets: 4,rxPackets: 4,lostPackets: 0,timesForwarded: 0],Flow[flowID: 4,timeFirstTxPacket: 1020243624,timeLastTxPacket: 1313872312,timeFirstRxPacket: 1030277223,timeLastRxPacket: 1324387511,delaySum: 51335996,jitterSum: 481600,lastDelay: 10515199,txBytes: 1082, rxBytes: 1082,txPackets: 5,rxPackets: 5,lostPackets: 0,timesForwarded: 0]],Ipv4FlowClassifier[Flow[flowId: 4, sourceAddress: 10.1.0.1, destinationAddress: 10.1.0.2, protocol: 6],Flow[flowId: 3, sourceAddress: 10.1.0.1, destinationAddress: 10.1.1.2, protocol: 6],Flow[flowId: 2, sourceAddress: 10.1.0.2, destinationAddress: 10.1.0.1, protocol: 6],Flow[flowId: 1, sourceAddress: 10.1.1.2, destinationAddress: 10.1.0.1, protocol: 6]],FlowProbes[FlowProbe[index: 0, stats: <FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4],FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4],FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4],FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4]>],FlowProbe[index: 1, stats: <FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4],FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4]>],FlowProbe[index: 2, stats: <FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4],FlowStats/[email protected][flowId: 1000, packets: 1000, bytes: 1000, delayFromFirstProbeSum: 1000, countdown: 4]>]]] 

확인하기 JVM 버그는 있지만 아무것도하지 않았다. 이상한가?

편집 3 :

나는 * 원자에 필드를 변경했습니다. 나는 진지하게 이것을 JVM 버그에 놓아야한다. 원자 필드가 최종적으로 내부적으로 디폴트 값에 의해 설정되고 NullPointerException이 발생하는 것을 볼 필요가있다.

protected final AtomicInteger flowId = new AtomicInteger(); 
protected final AtomicInteger packets = new AtomicInteger(); 
protected final AtomicInteger bytes = new AtomicInteger(); 
protected final AtomicLong delayFromFirstProbeSum = new AtomicLong(); 

예외 :

Exception in thread "FlowMonitor Updater" java.lang.NullPointerException 
    at kokuks.flowmon.FlowProbeFlowStats.toString(FlowProbeFlowStats.java:95) 

편집 4 : I 1.6, 동일한 문제의 안정된 버전으로 JDK1.7에서 변경되었습니다.

전 필드에 대해 생각해 봤지만 생성자에서 설정을 취소 한 다음 나중에 설정했습니다. 나는 이식의 순서가 확실치 않지만,이 경우 엉망이 될 수도 있습니다. 어쨌든, init 메소드에 넣고 그 것이 무엇인지 알아 보겠습니다. 단 하나의 클래스의 경우에는 기괴합니다. 그것은 다른 사람들을 위해 일합니다.

답변

0

설치 프로그램을 init 메소드로 옮겨서 문제를 해결했습니다. 생성자에서 모든 작업을 수행하면서 이상한 일이 있음이 드러났습니다. 그래서 왜 내가 Atomic * 필드에 접근하려고했을 때 null 이었는가? 이것은 상위 생성자에 대한 수퍼 콜이 먼저 발생했기 때문에 아직 설정되지 않았기 때문에 발생했습니다. 왜 다른 요소들은 괜찮 았던 것일까 요?하지만 해결했습니다.

1

출력에 이상한 점이 있습니다. ahaaaa2 접두사가 붙은 줄은 ahaaaa1 접두사가 붙은 줄 앞에 인쇄되어있는 것처럼 보입니다. 그러나 실제로는 ahaaaa2 행은 이전 값 세트에서 나오고 ahaaaa1 행은 다음 값 세트에서옵니다.

접두사가 ahaaaa1 인 접미사는 기본값 (0)입니다. ahaaaa2이있는 줄은 예상대로 올바른 값을 갖고있는 것 같습니다. 나는 System.out.println("ahaaaa2:: " + this.toString()) 이후에 개행을 추가했다면 결과가 정확하다는 것을 알았을 것입니다.


편집 : OK, 나는 마침내 문제를 참조하십시오. 최종 출력 라인의 끝에는 모든 통계를 다시 인쇄합니다. 이보고 기대하는 경우 :

FlowStats/[email protected][flowId: 0, packets: 0, bytes: 0, delayFromFirstProbeSum: 0] 

을 등 다른 FlowProbeFlowStats에 대한

내가 무슨 일이야에 관해서는하지 실마리가 객체 :

FlowStats/[email protected][flowId: 4, packets: 4, bytes: 762, delayFromFirstProbeSum: 0] 

를 대신 얻을 그러나 그 최종 행이 어디서 생성되는지, 그리고 그 동안에는 FlowProbeFlowStats 객체가 어떻게 될지에 대해서도 알지 못합니다. 코드를 더 이상 보지 않고도 내가 도울 수 있다고 생각하지 않습니다.

+0

두 번째 코드 블록에서 볼 수 있듯이 1과 2 변수가 쌍으로되어 있습니다. 나는 설정 작업이 끝난 후에 상태를 알리고 있습니다. 이상하게도, 클래스 변수를 망칠 것은 생성자에서만 이루어지며 필드는 정보를 숨긴다. 세터 또는 명확한 방법이 없습니다. 이 모든 작업은 단일 루핑 스레드에서도 수행되며 객체는 반복 작업간에 재사용되지 않습니다. –

+0

@Chris : 1 변수와 2 변수에 대해 무엇을 말하고 있는지 알고 있습니다. 내 요점은 내 눈에, 출력 형식 오해의 소지가 있었다; 처음에는 혼자서 버그가 있다고 생각하는 이유를 설명 할 수 있다고 생각했습니다. 위에서 지적한 것처럼 더 많은 코드를 보지 않고도 문제를 디버깅 할 수는 없습니다. (계속 ...) –

+0

@Chris : 당신이 취할 수있는 몇 가지 디버깅 단계를 제안 할 수 있습니다 : ** 1) ** 최종 출력 라인이 실제로 실행이 끝날 때 생성되는지 확인하십시오. 이전에, 그리고 어딘가에 버퍼링). ** 2) ** 필드의 이름 ('flowId','packets' 등)을 변경하면 변경해야한다고 생각하는 곳에서만 변경된다는 사실을 확실하게 알 수 있습니다.** 3) ** 일시적으로 toString() 결과에 필드'set'을 포함하십시오; 값이 0 인 경우 'true'이면, 아는 것이 재미있을 것입니다. –