<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Analysis Report Archives - WonderWall</title>
	<atom:link href="https://blog.wonderwall.me/category/analysis-report/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.wonderwall.me/category/analysis-report/</link>
	<description></description>
	<lastBuildDate>Sun, 11 Dec 2011 19:23:07 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8</generator>
	<item>
		<title>Implementation of java.util.Map 의 보이지 않는 위험</title>
		<link>https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/</link>
					<comments>https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/#comments</comments>
		
		<dc:creator><![CDATA[april1024]]></dc:creator>
		<pubDate>Sun, 11 Dec 2011 19:23:07 +0000</pubDate>
				<category><![CDATA[Analysis Report]]></category>
		<category><![CDATA[java XStream hang HashMap synchronized]]></category>
		<guid isPermaLink="false">http://blog.wonderwall.me/?p=210</guid>

					<description><![CDATA[<p>a pit of infinite loopeness 배경 Server scale-up 이후부터 Web Application을 배포하고 나면 몇시간 이내에 특정 서버의 CPU 사용률이 100%에 이르는 사태가 발생하였다. thread dump를 확인해 봐도 특별한 이상 징후는 발견되지 않았다. 단지 아래와 같이 여러 Thread 들이 java.util.WeakHashMap.get(WeakHashMap.java:355) 에 걸려있었으나, Thread.State가 RUNNABLE 이기 때문에 주의깊게 보지 않았다. 왜냐하면 지금까지 Java core package에서 문제가 발생한 &#8230; </p>
<p class="link-more"><a href="https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/" class="more-link">Continue reading<span class="screen-reader-text"> "Implementation of java.util.Map 의 보이지 않는 위험"</span></a></p>
<p>The post <a rel="nofollow" href="https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/">Implementation of java.util.Map 의 보이지 않는 위험</a> appeared first on <a rel="nofollow" href="https://blog.wonderwall.me">WonderWall</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>a pit of infinite loopeness</h2>
<h3>배경</h3>
<p>Server scale-up 이후부터 Web Application을 배포하고 나면 몇시간 이내에 특정 서버의 CPU 사용률이 100%에 이르는 사태가 발생하였다. thread dump를 확인해 봐도 특별한 이상 징후는 발견되지 않았다. 단지 아래와 같이 여러 Thread 들이 java.util.WeakHashMap.get(WeakHashMap.java:355) 에 걸려있었으나, Thread.State가 RUNNABLE 이기 때문에 주의깊게 보지 않았다. 왜냐하면 지금까지 Java core package에서 문제가 발생한 적은 한 번도 없거니와, Java core package를 의심하게 되면 밑도끝도 없이 모든것을 의심해야 하는 불상사가 발생하기 때문이다. 난 적어도 절친은 믿고 세상을 살아간다. 훗날 내 뒤통수를 칠 지언정&#8230;</p>
<pre lang="java">"TP-Processor233" daemon prio=10 tid=0x8d848800 nid=0x717d runnable [0x893f6000]
   java.lang.Thread.State: RUNNABLE
	at java.util.WeakHashMap.get(WeakHashMap.java:355)
	at com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer.unescapeName(XmlFriendlyReplacer.java:118)
	at com.thoughtworks.xstream.io.xml.AbstractXmlReader.unescapeXmlName(AbstractXmlReader.java:42)
	at com.thoughtworks.xstream.io.xml.AbstractPullReader.getNodeName(AbstractPullReader.java:199)
	at com.thoughtworks.xstream.io.ReaderWrapper.getNodeName(ReaderWrapper.java:44)
	at com.thoughtworks.xstream.io.path.PathTrackingReader.moveDown(PathTrackingReader.java:38)
	at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:199)
	at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:162)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:82)
	at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:63)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:76)
	at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:246)
	at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:218)
	at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:162)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:82)
	at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:63)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:76)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:60)
	at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:137)
	at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:33)
	at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:923)
	at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:909)
	at com.thoughtworks.xstream.XStream.fromXML(XStream.java:861)
</pre>
<p>문제가 된 web application에서 사용하는 XStream의 version이 1.3인데, 혹시나 하는 마음에 공식 XStream site에 들어가서 change history를 보다가 <a title="XSTR-584: Race condition in XmlFriendlyReplacer issue" href="http://jira.codehaus.org/browse/XSTR-584">XSTR-584: Race condition in XmlFriendlyReplacer issue</a>를 발견했다. Issue description 에는 내가 겪은 증상과 동일했고, 문제의 원인은 not synchronized java.util.WeakHashMap 을 사용했기 때문이라고 간단히 쓰여 있었다.</p>
<blockquote><p>com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer makes use of 2 WeakHashmaps to hold string.<br />
Those maps are accessed multi-threaded, but are not synchronized.</p>
<p>This can lead to access on those maps occupying all CPU-resources, which can only get solved by restarting the VM.<br />
This happens under rare heavily multi-threaded circumstances, nevertheless the impact is critical.</p></blockquote>
<h3>Implementation of java.util.Map이 가진 잠재적 문제점</h3>
<p>구글링을 해보니 Multi-threaded situation(under high concurrency) 에서 Implementation of java.util.Map 의 get() 호출 시 method 내부에서 infinite loop에 빠질 수 있다고 한다. 해당 되는 Implementation of java.util.Map 는 API Document에 아래와 같이 설명된 Class 들이다.</p>
<blockquote><p>Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be &#8220;wrapped&#8221; using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:</p>
<p>Map m = Collections.synchronizedMap(new HashMap(&#8230;));</p></blockquote>
<ul>
<li>java.util.HashMap</li>
<li>java.util.LinkedHashMap</li>
<li>java.util.TreeMap</li>
<li>java.util.WeakHashMap</li>
</ul>
<p>더욱이 문제는 대부분의 개발자들은 concurrency로 인한 data corruption 을 염두해두고 위 Class들을 자주 사용한다는 점이다. 즉 개발자가 Java Document의 &#8220;Note that this implementation is not synchronized&#8221; 의 의미를 race condition 에 의한 data corruption 까지만 이해하고 위 Class들을 자주 사용할수록, infinite loop에 빠질 확률이 더 높아진다.</p>
<p>그 결과 JVM hanging 뿐만 아니라 해당 서버에서 제공하는 서비스들(i.e daemon)까지도 CPU 자원을 사용할 수 없기 때문에 문제는 더욱 커진다. 이렇게 불시에 찾아와 CPU 자원을 모두 고갈시키는 불청객의 위험이 우리 주위에 도사리고 있다.</p>
<p><em>어느 CS 전공자가 위 Note만 보고 JVM이 hanging 될꺼라 예상할 수 있을까? 5년 넘게 Java language 의 API들을 많이 사용해 왔지만, 위 처럼 황당한 경우는 처음이다. 최소한 infinite loop 에 대한 경고는 해야 하지 않았을까? Synchronization에 따른 deadlock은 들어 봤어도, not synchronization에 따른 infinite loop는 들어 본 적이 없다.</em></p>
<h3>언제 infinite loop가 발생하는가?</h3>
<p>기가 막히게 제목을 잘 지은 <a title="A Beautiful Race Condition" href="http://mailinator.blogspot.com/2009/06/beautiful-race-condition.html">&#8220;A Beautiful Race Condition&#8221; article</a> 에서 infinite loop가 언제 발생할 수 있는지에 대해 설명이 잘 되어 있다.</p>
<p>java.util.HashMap.transfer() 를 호출하고 난 뒤 Entry[] table의 상태를 그려보았다.</p>
<ul>
<ul>
<li>normal case</li>
</ul>
</ul>
<p><a href="http://192.168.1.101/wordpress/wp-content/uploads/2011/12/java.util_.HashMap.resize_normal.png"><img fetchpriority="high" decoding="async" class="alignnone size-full wp-image-240" title="java.util.HashMap.resize() in normal" src="http://192.168.1.101/wordpress/wp-content/uploads/2011/12/java.util_.HashMap.resize_normal.png" alt="" width="542" height="521" srcset="https://blog.wonderwall.me/wp-content/uploads/2011/12/java.util_.HashMap.resize_normal.png 542w, https://blog.wonderwall.me/wp-content/uploads/2011/12/java.util_.HashMap.resize_normal-300x288.png 300w" sizes="(max-width: 542px) 100vw, 542px" /></a></p>
<ul>
<ul>
<li>abnormal case</li>
</ul>
</ul>
<p><a href="http://192.168.1.101/wordpress/wp-content/uploads/2011/12/java.util_.HashMap.resize_abnormal.png"><img decoding="async" class="alignnone size-full wp-image-247" title="java.util.HashMap.resize() in abnormal" src="http://192.168.1.101/wordpress/wp-content/uploads/2011/12/java.util_.HashMap.resize_abnormal.png" alt="" width="553" height="521" srcset="https://blog.wonderwall.me/wp-content/uploads/2011/12/java.util_.HashMap.resize_abnormal.png 553w, https://blog.wonderwall.me/wp-content/uploads/2011/12/java.util_.HashMap.resize_abnormal-300x283.png 300w" sizes="(max-width: 553px) 100vw, 553px" /></a></p>
<ul>
<ol>
<li>2개 이상의 thread가 Map에 동시에 write할 때 rehash의 조건이 true 이면</li>
<li>Map의 어느 bucket의 Entry.next 가 서로를 가리킨다. infinite loop 생성</li>
<li>infinite loop Entry가 있는 bucket 을 read 할 때 해당 thread는 hanging</li>
</ol>
</ul>
<h3>대응 방법</h3>
<ol>
<li>java.util.concurrent.ConcurrentHashMap 사용</li>
<li>Collections.synchronizedMap method 사용하여 wrapping</li>
<li>mutator method 에 접근 할 때 synchronized 처리</li>
</ol>
<p>The post <a rel="nofollow" href="https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/">Implementation of java.util.Map 의 보이지 않는 위험</a> appeared first on <a rel="nofollow" href="https://blog.wonderwall.me">WonderWall</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonderwall.me/2011/12/12/implementation-of-java-util-map-%ec%9d%98-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Jakarta Project 에피소드 Ⅰ: ORO의 보이지 않는 위험</title>
		<link>https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/</link>
					<comments>https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/#respond</comments>
		
		<dc:creator><![CDATA[april1024]]></dc:creator>
		<pubDate>Sun, 21 Mar 2010 12:36:30 +0000</pubDate>
				<category><![CDATA[Analysis Report]]></category>
		<category><![CDATA[Jakarta]]></category>
		<category><![CDATA[ORO]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[regular expression]]></category>
		<category><![CDATA[Savarese]]></category>
		<category><![CDATA[자카르타]]></category>
		<category><![CDATA[정규표현식]]></category>
		<guid isPermaLink="false">http://blog.wonderwall.me/?p=11</guid>

					<description><![CDATA[<p>Jakarta Project 에피소드Ⅰ ORO의 보이지 않는 위험 조금 먼 옛날 Jakarta Project 저편에… 1996년 1월 23일 JDK 1.0이 세상에 처음 나온 이후 예상과 달리 많은 사람들로부터 관심을 받기 시작한다. 인기가 많아 질수록 언어 스펙 역시 요구가 많아지게 되는데, 그 중에 하나가 불편한 text-processing이었다. 때마침 1999년 Java Language 창시자인 James Gosling과 Open source 수호자인 Brian Behlendorf가 &#8230; </p>
<p class="link-more"><a href="https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/" class="more-link">Continue reading<span class="screen-reader-text"> "Jakarta Project 에피소드 Ⅰ: ORO의 보이지 않는 위험"</span></a></p>
<p>The post <a rel="nofollow" href="https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/">Jakarta Project 에피소드 Ⅰ: ORO의 보이지 않는 위험</a> appeared first on <a rel="nofollow" href="https://blog.wonderwall.me">WonderWall</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure id="attachment_77" aria-describedby="caption-attachment-77" style="width: 600px" class="wp-caption aligncenter"><a href="https://blog.wonderwall.me/?attachment_id=77" rel="attachment wp-att-77"><img decoding="async" class="size-full wp-image-77" title="Jakarta Project : Episode 1" src="http://192.168.1.101/wordpress/wp-content/uploads/2010/03/intro1.png" alt="Jakarta Project : Episode 1" width="600" height="248" srcset="https://blog.wonderwall.me/wp-content/uploads/2010/03/intro1.png 600w, https://blog.wonderwall.me/wp-content/uploads/2010/03/intro1-300x124.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></a><figcaption id="caption-attachment-77" class="wp-caption-text">Jakarta Project : Episode 1</figcaption></figure>
<p style="text-align: center;"><span style="font-size: 16pt;"><strong>Jakarta Project 에피소드Ⅰ</strong></span></p>
<p style="text-align: center;"><span style="font-size: 12pt;">ORO의 보이지 않는 위험</span></p>
<h3>조금 먼 옛날 Jakarta Project 저편에…</h3>
<p>1996년 1월 23일 JDK 1.0이 세상에 처음 나온 이후 예상과 달리 많은 사람들로부터 관심을 받기 시작한다. 인기가 많아 질수록 언어 스펙 역시 요구가 많아지게 되는데, 그 중에 하나가 불편한 text-processing이었다.</p>
<p>때마침 1999년 Java Language 창시자인 James Gosling과 Open source 수호자인 Brian Behlendorf가 만나서 <a href="http://www.javaworld.com/javaworld/jw-06-1999/jw-06-sunapache.html?page=1">Jakarta Project를 설립</a> 하고, Jakarta Project에 힘입은 Savarese는 2000년 7월에 Jakarta ORO project를 발족하여 Java Language에서 Regular Expression(정규 표현식)을 사용할 수 있게 하는데…</p>
<h3>Jakarta ORO란?</h3>
<p>JAVA는 <a href="http://en.wikipedia.org/wiki/Sun_java#Version_history"><em>J2SE 1.4</em> (February 6, 2002)</a>때부터 Regular Expression(정규 표현식)을 지원하기 시작했다. 그러므로 초창기 JAVA는 text-processing이 타 언어에 비해 사용이 불편했다. <a href="http://jakarta.apache.org/site/news/news-2000.html">2000년 7월 23일</a> <a href="http://www.savarese.org/oro/index.html">ORO(Original Reusable Objects) company</a>가 JAVA에서 Regular Expression을 사용할 수 있도록 하기 위해 Set of text-processing Java classes를 Jakarta project에 기증하였다. 그 project가 바로 <a href="http://jakarta.apache.org/oro/index.html">ORO project</a>이다.</p>
<h3>Jakarta ORO가 가진 잠재적 문제점</h3>
<p>ORO project는 2003년 12월 30일 마지막 release이후, 많은 개발자로부터 J2SE 1.4에 포함된 JAVA CORE regular expression package(java.util.regex)에 비해서 현저히 떨어지는 성능과 높은 메모리 사용률에 대한 개선 요구사항들이 쇄도하게 된다. 이에 대해 original code contributor인 Daniel Savarese는 J2SE 1.4 이후 추가된 java.lang.CharSequence를 사용하면 위 언급한 성능/메모리에 대한 요구사항을 만족시킬 수는 있지만, backward compatibility(J2SE 1.4 이전 하위 호환성) 문제 때문에 <a href="http://www.mail-archive.com/oro-user@jakarta.apache.org/msg00534.html">요구사항을 들어줄 수 없었다고 한다</a>.</p>
<p>그러므로 org.apache.oro package는 Perl5/AWK-like compatible regular expression을 사용할 수 있다는 장점이 있으나, java core regular expression package에 비해 현저히 떨어지는 성능과 높은 메모리 사용률이라는 단점 때문에 이를 감수하면서 사용할 경우, 언제 running service에 장애가 발생할 지 모른다.</p>
<p>더 큰 문제는 <a href="http://jakarta.apache.org/oro/users.html">J2SE 1.4 이전에 개발 시작한 open source</a>가 ORO package를 많이 사용하고 있으며, 특히 <a href="http://jakarta.apache.org">Jakarta subproject</a> 상당수가 ORO package를 사용하고 있는 실정이란 점이다.</p>
<h3>대응 방법</h3>
<p>ORO package에 dependent한 대표적 open source인 spring framework, Jakarta ant 그리고 json-lib가 어떻게 ORO package를 사용하고 있는지 살펴봤다.</p>
<p>Json-lib와 spring framework는 JAVA version 1.4를 기준으로 ORO에 binding할지 Java core regular expression에 binding할지를 결정한다. 그러므로 version 1.4 이후의 JAVA를 사용하면 ORO에 binding되지 않기 때문에 ORO의 잠재적 문제로부터 안전하다.</p>
<p>한편 Jakarta ant는 default로 Java core regular expression에 binding되기 때문에 애초부터ORO의 잠재적 문제로부터 벗어날 수 있다. (jakarta ant는 <a href="http://ant.apache.org/manual/Types/regexp.html">property설정</a>으로 jakarta ORO, Jakarta Regexp, Java core regular expression중 하나를 선택하여 사용하는 구조임)</p>
<p>위 3가지 open source 조사결과로 미루어 볼 때, ORO는 backward compatibility를 제공하는데 주로 사용되며 version 1.4 이후의 JAVA를 사용할 경우에는 ORO에 binding되지 않을 것이라 추측한다. 왜냐하면 2002년 JAVA version 1.4가 release된 이후 open source는 많은 사람들로부터 오랜 기간 동안 사용되면서 충분히 검증 받은 code라고 생각하기 때문이다. 하지만 직접 눈으로 확인하는 것이 가장 확실한 방법이다.</p>
<p><strong>정리하면,</strong></p>
<ul>
<li><strong>The latest stable version of JAVA(가장 최신의 안정버전)를 사용한다.</strong></li>
<li><strong>규모가 작은 open source일 경우 직접 눈으로 확인한다.</strong></li>
</ul>
<h3>대응 방법 예시 (직접 눈으로 source code 검증)</h3>
<ol>
<li><a href="http://json-lib.sourceforge.net">json-lib</a> (version 2.2.2)
<ul>
<ul>
<li>source code &gt; net.sf.json.regexp.RegexpUtils.java</li>
</ul>
</ul>
<pre class="lang:java decode:true">package net.sf.json.regexp;

public class RegexpUtils {
…
(중간 생략)
…

   /**
    * Returns a RegexpMatcher that works in a specific environment.

    * When in a JVM 1.3.1 it will return a Perl5RegexpMatcher, if the JVM is
    * younger (1.4+) it will return a JdkRegexpMatcher.
    */
   public static RegexpMatcher getMatcher( String pattern ) {
      if( isJDK13() ){
         return new Perl5RegexpMatcher( pattern );
      }else{
         return new JdkRegexpMatcher( pattern );
      }
   }

…
(중간 생략)
…
}
</pre>
<ul>
<ul>
<li>Inheritance diagram</li>
</ul>
</ul>
<p><img decoding="async" src="http://192.168.1.101/wordpress/wp-content/uploads/2010/03/032110_1237_JakartaProj11.png" alt="Inheritance diagram" /></li>
<li><a href="http://www.springsource.org">spring framework</a> (version 2.0.6)
<ul>
<ul>
<li>source code &gt; org.springframework.aop.support.RegexpMethodPointcutAdvisor.java</li>
</ul>
</ul>
<pre class="lang:java decode:true ">package org.springframework.aop.support;
…
(중간 생략)
…

public class RegexpMethodPointcutAdvisor extends AbstractGenericPointcutAdvisor {

…
(중간 생략)
…

	/**
	 * Create the actual pointcut: By default, a {@link Perl5RegexpMethodPointcut}
	 * will be created if Perl5 syntax is enforced or when running on JDK 1.3.
	 * Else, a {@link JdkRegexpMethodPointcut} (JDK 1.4+) will be used.
	 * @return the Pointcut instance (never &lt;code&gt;null&lt;/code&gt;)
	 * @see #setPerl5
	 * @see Perl5RegexpMethodPointcut
	 * @see JdkRegexpMethodPointcut
	 */
	protected AbstractRegexpMethodPointcut createPointcut() {
		if (this.perl5 || JdkVersion.getMajorJavaVersion() &lt; JdkVersion.JAVA_14) { 
			// needs Jakarta ORO on the classpath 
			return Perl5RegexpPointcutFactory.createPerl5RegexpPointcut(); 
		} else { 
			// needs to run on JDK &gt;= 1.4
			return new JdkRegexpMethodPointcut();
		}
	}

…
(중간 생략)
…
}
</pre>
<ul>
<ul>
<li>Inheritance diagram</li>
</ul>
</ul>
<p><img decoding="async" src="http://192.168.1.101/wordpress/wp-content/uploads/2010/03/032110_1237_JakartaProj21.png" alt="Inheritance diagram" /></li>
<li><a href="http://ant.apache.org">Jakarta Ant</a> (version 1.8)
<ul>
<ul>
<li>source code &gt; org.apache.tools.ant.util.regexp.RegexpFactory.java</li>
</ul>
</ul>
<pre class="lang:java decode:true">package org.apache.tools.ant.util.regexp;
…
(중간 생략)
…
public class RegexpFactory extends RegexpMatcherFactory {
…
(중간 생략)
…
   /**
    * Create a new regular expression matcher instance.
    * Available implementations:
    *
    *   org.apache.tools.ant.util.regexp.Jdk14RegexpRegexp (default)
    *        Based on the JDK's built-in regular expression package
    *
    *   org.apache.tools.ant.util.regexp.JakartaOroRegexp
    *        Based on the jakarta-oro package
    *
    *   org.apache.tools.ant.util.regexp.JakartaRegexpRegexp
    *        Based on the jakarta-regexp package
    *
    * @param p Project whose ant.regexp.regexpimpl property will be used.
    * @return the matcher instance
    * @throws BuildException on error
    */
    public Regexp newRegexp(Project p) throws BuildException {
        String systemDefault = null;
        if (p == null) {
            systemDefault = System.getProperty(MagicNames.REGEXP_IMPL);
        } else {
            systemDefault = p.getProperty(MagicNames.REGEXP_IMPL);
        }

        if (systemDefault != null) {
            return createRegexpInstance(systemDefault);
            // XXX     should we silently catch possible exceptions and try to
            //         load a different implementation?
        }

        return new Jdk14RegexpRegexp();//         default
    }
…
(중간 생략)
…

}
</pre>
<ul>
<ul>
<li>Inheritance diagram</li>
</ul>
</ul>
<p><img decoding="async" src="http://192.168.1.101/wordpress/wp-content/uploads/2010/03/032110_1237_JakartaProj31.png" alt="Inheritance diagram" /></li>
</ol>
<p>The post <a rel="nofollow" href="https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/">Jakarta Project 에피소드 Ⅰ: ORO의 보이지 않는 위험</a> appeared first on <a rel="nofollow" href="https://blog.wonderwall.me">WonderWall</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.wonderwall.me/2010/03/21/jakarta-project-%ec%97%90%ed%94%bc%ec%86%8c%eb%93%9c-%e2%85%a0-%eb%b3%b4%ec%9d%b4%ec%a7%80-%ec%95%8a%eb%8a%94-%ec%9c%84%ed%97%98/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
