try-with-resourcesã®ã³ã³ãã€ã«ãšéã³ã³ãã€ã«ããŸãã¯ãã°ã®ä¿®æ£æ¹æ³ãšãã®åå ã«ã€ããŠã®ã¹ããŒãªãŒã
ã¯ããã«

ãã°ããåã«ãã¯ãŒãã³ã°ãã©ããã®ããã¯ãã°ã¯ã»ãšãã©ç©ºã§ãããããŸããŸãªç 究ã¿ã¹ã¯ãæµ®äžããŸããã ãããã®1ã€ã¯éåžžã«
èå³æ·±ããã«èãããŸããïŒ
PITestã䜿çšããŠãããžã§ã¯ãã«çªç¶å€ç°ãã¹ãã
åºå®ããããš ã Habréã«ã¯ããã§ã«ãã®ã©ã€ãã©ãªã®éåžžã«
詳现ãªæŠèŠããããŸãïŒäŸãšåçä»ãïŒã ç§ã¯ãã®èšäºãç§èªèº«ã®èšèã§èªãã€ããã¯ãããŸããããããã§ãåãã£ãŠãããç解ããããšããå§ãããŸãã
çªç¶å€ç°ãã¹ãã®ã¢ã€ãã¢ãçãŸããããšã¯èªããŸãã äœåãªåŽåãã»ãšãã©ãããããšãªããã³ãŒãå
ã®æœåšçã«å±éºãªå ŽæãèŠã€ããããã®ããŒã«ãå
¥æãã䟡å€ããããŸãïŒ é
æ»ãªãä»äºã«åãããããŸããã åœæãã©ã€ãã©ãªã¯æ¯èŒçè¥ãããã®çµæãéåžžã«ç²éãªãã®ã§ãããããã§ã¯ãMavenã®èšå®ã§å°ãéã¶å¿
èŠããããŸããããã§ãSonarã®ãã©ã°ã€ã³ã«ããããåœãŠãŸãã ãããããã°ããããŠããããžã§ã¯ãå
šäœããã§ãã¯ã¢ãŠãããããšãã§ããŸããã çµæïŒæ°çŸã®çãæ®ã£ãçªç¶å€ç°ïŒ ãã«ããµãŒããŒã§ã®é²åãã¹ã±ãŒã«ããŸãã
è¢ããŸãããä»äºã«çªå
¥ããŸããã äžéšã®ãã¹ãã§ã¯ãã¹ã¿ãã®ååãªæ€èšŒãè¡ãããŸããããä»ã®ãã¹ãã§ã¯ãããžãã¯ã®ä»£ããã«ãäžè¬ã«ãã¹ã察象ãæ確ã§ã¯ãããŸããã ç·šéãæ¹åãæžãæãã äžè¬ã«ãããã»ã¹ã¯å§ãŸããŸããããçãæ®ã£ãçªç¶å€ç°ã®æ°ã¯ç§ãã¡ãæãã»ã©æ¥éã«æžå°ããŸããã§ããã çç±ã¯ç°¡åã§ãããPITã¯ã
try-with-resourcesãããã¯ã§èšå€§ãªæ°ã®èª€æ€ç¥ãäžããŸããã çãæ€çŽ¢ã§ããã®
ãã°ã¯æ¢ç¥ã§ããããŸã ä¿®æ£ãããŠããªãããšã瀺ãããŸããã ããŠãã©ã€ãã©ãªã³ãŒãã¯å
¬éãããŠããŸãã ãªã圌ã説åŸããåé¡ãäœã§ããããèŠãŠã¿ãŸãããïŒ
ç§ãã¡ã¯ãã®çç±ãç解ããŠããŸã
æãåçŽãªäŸã§ããåäœãã¹ããæããŠãPITestãå®è¡ããŸããã çµæã¯ããªãã®åã«ãããŸãã1ã€ã§ã¯ãªããçãæ®ã£ãçªç¶å€ç°ã11åããããã®ãã¡10åãã}ãèšå·ã®ããè¡ãæããŠããŸãã
closeããã³
addSupressedã¡ãœããã®åŒã³åºãã¯ããã®è¡ã«try-with-resourcesãããã¯çšã«çæãããã³ãŒããå«ãŸããããšã瀺åããŠããŸãã ãã®æšæž¬ã確èªããããã«ãã¯ã©ã¹ãã¡ã€ã«ãéã³ã³ãã€ã«ããããšã«ããŸããã ãããè¡ãã«ã¯ã
JD-GUIã䜿çšããŸãããã
IntelliJ IDEA 14çµã¿èŸŒã¿ã®é
ã³ã³ãã€ã©ãŒããå§ãããŸãã
public static void main(String[] args) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); Throwable var2 = null; try { baos.flush(); } catch (Throwable var11) { var2 = var11; throw var11; } finally { if (baos != null) { if (var2 != null) { try { baos.close(); } catch (Throwable var10) { var2.addSuppressed(var10); } } else { baos.close(); } } } }
æšæž¬ã¯ç¢ºèªãããŸããããçåãæ®ããŸããã2ã€ã®try-with-resourcesè¡ãã©ã®ããã«ããŠ12åã®try-catch-finallyè¡ã«ãªã£ãã®ã§ããããïŒ
gvsmirnov ã¯ã OpenJDKãœãŒã¹ãããŠã³ããŒã
ããããã«ãç解ã§ããªãç¶æ³ã§
ç§ãã¡ã«
éºèŽãããŸããã ããã¯ç§ããã£ãããšã§ãã
try-with-resourcesã³ã³ãã€ã«ã¿ã¹ã¯ã«é¢é£ãããã¹ãŠã®ã³ãŒãã¯ã
Lowerã¯ã©ã¹ã®1428è¡ãš1580è¡ã®éã«ãããŸãã Javadocã¯ããã®ã¯ã©ã¹ã¯æ§æç³ã翻蚳ããããã«èšèšãããŠããããšã瀺ããŠããŸããéæ³ã§ã¯ãªããæ§æããªãŒã®æãåçŽãªå€æŽã®ã¿ã§ãã ãã¹ãŠã
JLS 14.20.3ã«æºæ ããŠããŸãã
ã³ã³ãã€ã©ã®åäœãææ¡ããŸããã ã©ã€ãã©ãªãŒãã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããã³ãŒããå€æŽããããšããŠããçç±ãšãã®åäœæ¹æ³ãç解ããããšã¯æ®ã£ãŠããŸãã ãœãŒã¹ã調ã¹ãŠã¿ããšã次ã®ããšãããããŸããã PITestã¯ãRAMã«ããŒãããããã€ãã³ãŒãã®ã¿ãæäœããŸãã ç¹å®ã®ã«ãŒã«ã«åŸã£ãŠåœä»€ã眮ãæããåäœãã¹ããå®è¡ããŸãã ãã€ãã³ãŒãã§ã®äœæ¥ã«ã¯
ASMã䜿çšãããŸãã
æåã®ã¢ã€ãã¢ã¯ãMethodVisitorã¯ã©ã¹ã®visitGeneratedTryCatchBlockã¡ãœããããè¡çªå·ãã€ã³ã¿ãŒã»ããããã©ã€ãã©ãªã«ç¡èŠããè¡ãæ瀺ããããšã§ããã finallyãããã¯ã«ã¯ãåæ§ã®æ©èœããã§ã«
å®è£
ãããŠããŸãã ããããvisitGeneratedTryCatchBlockã¡ãœãããååšããªãããšãç¥ã£ãŠé©ããã ASMã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããã³ãŒããšããã°ã©ããŒã«ãã£ãŠçæãããã³ãŒããåºå¥ããŸããã åŸ
ã¡äŒãã ãã€ãã³ãŒãã調ã¹ãå¿
èŠããããŸããããã®åºåãšãã©ãŒãããã¯
Textifierã«ãã£ãŠèŠªåã«æäŸãã
ãŸãã ã
TryExampleã¯ã©ã¹ã®ã¡ã€ã³ã¡ãœããã®ãã€ãã³ãŒã try-catch-finallyãããã¯ãJVMã¬ãã«ã§å®è£
ããããšããåçŽãªä»®å®ã¯
確èªãããŠ
ããŸãã ã ç¹å¥ãªæ瀺ã¯ãªããäŸå€ããŒãã«ãšã©ãã«éã®ãžã£ã³ãã®ã¿ããããŸãã æšæºã§ã¯ãçæããããããã¯ãèªèããããšãæ©èœããªãããšãããããŸãã å¥ã®ãœãªã¥ãŒã·ã§ã³ãæ¢ãå¿
èŠããããŸãã
ããã...
ã³ãŒããŒãããæšæž¬ããåã«ãéã³ã³ãã€ã«ãããã¯ã©ã¹ã«ãã€ãã³ãŒãããŒã¯ãä»ããããšã«ããŸããã ããããã®çµæã§ãã
public static void main(String[] args) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream();
ããã°ã©ã å®è¡ã®2ã€ã®äž»ãªæ¹æ³ãæããã«ãªã£ãŠããŸãã
L11 L12 L3 {L4 [L0ïŒL2 L15 L16ïŒL1] L14} L13
L11 L12 L3 [L5 {L6] L10 [L7ïŒL9 L19 L20ïŒL8] L18 L17}
äºãã®äžã«ã¯ãã³ãŒããããã¯ãäžèŽãŸãã¯ã»ãŒäžèŽããã©ãã«ããããŸãã æ¬åŒ§å
ã¯ã
closeã¡ãœãããäŸå€ãã¹ããŒãããšãã«å®è¡ãããã³ãŒãã§ãã åæ§ã«æ£æ¹åœ¢ã§-
ãã©ãã·ã¥ã¡ãœããã®å Žåã finallyãããã¯ãã³ã³ãã€ã©ã«ãã£ãŠ2å眮æãããããã2ã€ã®æ¹æ³ãå€æããŸããã ããŠãèŠèŠããŒãµãŒãå®å
šã«å£ãããã«ãäžæ¬åŒ§å
ã®ã©ãã«ã¯11è¡ç®ãåç
§ããŠããŸããPITestã®èª€æ€ç¥ã¯åãè¡ãåç
§ããŠããŸãã
ããã解決çã§ãïŒ æå°éã®ç¹°ãè¿ãåœä»€ã»ããã匷調衚瀺ããå¿
èŠããããŸãã ãã®ãããªã»ããããã¹ã察象ã®ãã€ãã³ãŒãã§èŠã€ãã£ãå Žåãããã«ã¯1è¡ã§èŠã€ãã£ãå Žåã¯ãtry-with-resourcesãããã¯çšã«çæãããã³ãŒããå©çšå¯èœã§ãã ããã»ã©é£ããé³ã§ã¯ãããŸããããè©ŠããŠã¿ãããšã«ããŸããã 以äžã¯ãç§ãæçµçã«è¡ã£ãæ瀺ã®ãªã¹ãã§ãã
private static final List<Integer> JAVAC_CLASS_INS_SEQUENCE = Arrays.asList( ASTORE,
ãã®ãããªãã®ã¯ãfinallyãããã¯ã®ã³ãŒãã«ãããã§ããŸãã
} finally { if (closeable != null) {
ããããªã«é£ãããªãããšç§ã¯æ°æ¥éã®ããŒãã¯ãŒã¯ã®åŸã«èããŸããã
ããã«ããã€ãã®äŸãæããŸããã ãããã䜿çšãããã¹ããäœæããŸããã ãã¹ãŠãããŸãããããã¹ãŠãæ©èœããŸãã PITestããã«ãããŠãã©ã€ãã³ãŒãã§å®è¡ããããšããŸããããã¹ãã¯å€±æããŸããã ç§ãæžãããã®ã§ã¯ãããŸããã ãã®ä»ã
ã³ã³ãã€ã©ã¯ç°ãªããŸã
ãã®ãããã³ãŒãã¯ãã³ã³ãã€ã«ããªããã¹ããŒãžãããåäœããªããã¹ããŒãžã«ç§»åããŸããã ãããèœã¡ãåã«ååšãããã¹ãã®1ã€ã ããŒã«ããã¯-ããã¯åäœããŸãã ãã¹ãå
ã§ããããžã§ã¯ãã«æ¢ã«ååšããŠãã
Java7TryWithResources.class.binãã¡ã€ã«ããã§ãã¯ãããŸãã ãã€ãã³ãŒããå°å·ããã®ã§ãç§ã¯ä¿¡ããããŸããã§ãããtry-with-resourcesãã³ã³ãã€ã«ããããã«ããŸã£ããç°ãªãé åºã®åœä»€ã䜿çšãããŸããã
ãããã¯ã«ãªããªãããã«ãæå
ã«ãããã¹ãŠã®ã³ã³ãã€ã©ããã§ãã¯ãå§ããŸããã Oracle JDKã®javacã§äœæ¥ããŸããããOpenJDKã®javacã§ãåæ§ã®çµæãåŸãããŸããã ç§ã¯ããŸããŸãªããŒãžã§ã³ãè©ŠããŸããïŒç¡é§ã«ã æå
ã«ãªãã£ãã®ã¯ã³ã³ãã€ã©ãŒã®è»¢æã§ããã Javaçšã®Eclipseã³ã³ãã€ã©ãECJã ã³ã³ãã€ã«ãããå°å·ããããã€ãã³ãŒã-äžèŠãããšãç§ãæ¢ããŠãããã®ã®ããã«èŠããŸãã
ECJã¯ã©ã¹ã«ããTryExampleã®ã¡ã€ã³ã¡ãœããã®ãã€ãã³ãŒã ãã®åŸãçµæã®ã¯ã©ã¹ãã¡ã€ã«ãéã³ã³ãã€ã«ããããšã«ããŸããã ãã³ã³ãã€ã©ã®çµæã¯ãã³ã³ãã€ã«ããã¯ãæåŠããŸããã ãŸããäœããããªãã¯ãã§ã«ããã§äœæ¥ããããšãã§ããŸãã ãã€ãã³ãŒãã«åŸã£ãŠããã°ã©ã ã³ãŒããæã£ãŠããæãç§ã¯ä»¥äžãåŸãŸããã
public static void main(String[] paramArrayOfString) throws Throwable { Throwable primaryExceptionVariable = null;
ECJã¯ãtry-with-resourcesãã³ã³ãã€ã«ããããã«ãŸã£ããç°ãªãã¢ãããŒããåããŸãã ã©ãã«ã¯èããå°ãããã³ãŒãã®ãããã¯ã¯èãã倧ãããªããŸãã è¥å€§åããããŒãã«ã®ä»£ããã«ãäŸå€ã¯åçŽã«æ¬¡ã®ã¬ãã«ã«ã¹ããŒãããŸãã
ããè€éãªäŸã§ã¯ãå
¥ãå人圢ã®ãããªãã®ã§ããããšãããããŸãã
ãã³ãããã®äžã«ã¯äœããããŸããïŒ ãœãŒã¹ãããŠã³ããŒããã«è¡ããŸãããä»åã¯
ECJã§ãã
tryã¹ããŒãã¡ã³ãã®ã³ã³ãã€ã«ã¯ã
TryStatementãã¡ã€ã«ã«é ãããŠ
ããŸãã ä»åã¯ãããªãŒã¯ãªãããªãã³ãŒãã®ã¿ãããŒãã³ã¢ã®ã¿ã§ãã try-with-resourcesã®è²¬ä»»ãè² ããã€ãã³ãŒãã¯ã500è¡ç®ãš604è¡ç®ã«çæãããŸããã³ãããã®å±¥æŽããã
tryãããã¯ã®æ¬äœã¯ããªãœãŒã¹ãäœæããã³éããããã®äžé£ã®åŒã³åºãã«ãã£ãŠåçŽã«æ§æãããŠããããšãããããŸãã
ãªããªã finallyãããã¯ã®çœ®æããªãå Žåãã³ãŒãã®éè€ã¯ãããŸããã ãã ãããã¹ãã®ãããç°ãªãäŸå€ã«å¯ŸããŠåãã¢ã¯ã·ã§ã³ãç¹°ãè¿ãããŸãã ãããå©çšããŸããã ECJã®äžé£ã®æ瀺ã¯æ¬¡ã®ãšããã§ãã
private static final List<Integer> ECJ_INS_SEQUENCE = Arrays.asList( ASTORE,
ãã®ããã察å¿ããJavaã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
if (throwable1 == null) {
æ®ãã®ã³ã³ãã€ã©ã¯ã©ãã§ããïŒ AspectJãECJãšã»ãŒåããã€ãã³ãŒããçæããããšãå€æããŸããã 圌ã«ãšã£ãŠãå¥ã®ã·ãŒã±ã³ã¹ãçºæããå¿
èŠã¯ãããŸããã§ããã IBMããã³ã³ãã€ã©ãŒãããŠã³ããŒãã§ããŸããã§ããïŒå®éã«ããŠã³ããŒãããããããŸããã§ããïŒã æ®åçãäœããããä»ã®ã³ã³ãã€ã©ã¯ç¡èŠãããŸããã
çµæ
泚ææ·±ãèªè
ã¯ãjavacã®äžé£ã®æ瀺ã1ã€ã®ãã¥ã¢ã³ã¹ãèæ
®ããŠããªãããšã«ãã§ã«æ°ä»ããŠããŸãã ã¯ã©ã¹ã¡ãœãããšã€ã³ã¿ãŒãã§ã€ã¹ã¡ãœãããåŒã³åºãã«ã¯ãå®éã«ã¯ããããINVOKEVIRTUALãšINVOKEINTERFACEãšããç°ãªãåœä»€ã䜿çšãããŸãã äžèšã®å®è£
ã§ã¯ãæåã®ã±ãŒã¹ã®ã¿ãèæ
®ããã2çªç®ã®ã±ãŒã¹ã¯èæ
®ãããŸããã ãŸããäœããä¿®æ£ããã®ã¯é£ãããããŸããã
çµæã¯ã©ããªããŸããïŒ
ãŸããäœæ¥ã®äž»ãªçµæã¯ãèšäºã®åé ã§èšåãããã°ãä¿®æ£ãããããã§ããã ã»ãšãã©ãã¹ãŠã®ã³ãŒãã¯1ã€ã®ã¯ã©ã¹ã«åãŸããŸãïŒãã¹ãã¯ã«ãŠã³ãããŸããïŒãããã¯çŸåšã
TryWithResourcesMethodVisitorã®ããã«ãªã£ãŠããŸãã ãã®åé¡ã解決ããããã®æè¯ã®éžæè¢ãæ¹å€ããææ¡ããããšãçã«å§ããŸãã
次ã«ãtry-with-resourcesãããã¯ãã³ã³ãã€ã«ããæ¹æ³ãèŠã€ããŸããã ãã®çµæãtry-catch-finallyããã€ãã³ãŒãã¬ãã«ã§ã©ã®ããã«èŠããããèŠã€ããŸããã ããŠãå¯ç£ç©ã¯
èšäºã®ç¿»èš³ã§ããã
第äžã«ãç§ã¯ããªãã«ãã¹ãŠãèšã£ããã®èšäºãæžããŸããã ããããä»ãããªãã®1人ããç²åŸããç¥èã䜿çš
ããŠã
浪費ã®åºæ¬çãª
ä¿æ°ãå¢ããããšãã§ããã§ãããã
ãããŠã䜿çšãšé埳ã¯ã©ãã«ãããŸããïŒ ç§ã¯åœŒãã®æ€çŽ¢ãèªè
ã«ä»»ããŸãã ç§ã¯ãã®èšäºãæžããŠããéãç§ã楜ããã ããšã ãã«æ³šæããŸãã èªãã§ããã ããã幞ãã§ãã ããããïŒ
PSããŒãã¹ãšããŠãJoshua Blochããã®try-with-resourcesã®å®è£
ã«é¢ããåæã®ææ¡ãæ€èšããããšããå§ãããŸãã
é¢çœããã§ãã
{ final LocalVariableDeclaration ; boolean #suppressSecondaryException = false; try Block catch (final Throwable #t) { #suppressSecondaryException = true; throw #t; } finally { if (#suppressSecondaryException) try { localVar.close(); } catch(Exception #ignore) { } else localVar.close(); } }