1.1 --- a/java/reflexe/nbproject/build-impl.xml Sat Nov 19 22:28:08 2016 +0100
1.2 +++ b/java/reflexe/nbproject/build-impl.xml Sat Nov 19 22:29:10 2016 +0100
1.3 @@ -191,7 +191,12 @@
1.4 </not>
1.5 </and>
1.6 </condition>
1.7 - <property name="javac.fork" value="${jdkBug6558476}"/>
1.8 + <condition else="false" property="javac.fork">
1.9 + <or>
1.10 + <istrue value="${jdkBug6558476}"/>
1.11 + <istrue value="${javac.external.vm}"/>
1.12 + </or>
1.13 + </condition>
1.14 <property name="jar.index" value="false"/>
1.15 <property name="jar.index.metainf" value="${jar.index}"/>
1.16 <property name="copylibs.rebase" value="true"/>
1.17 @@ -217,6 +222,7 @@
1.18 <condition else="" property="testng.debug.mode" value="-mixed">
1.19 <istrue value="${junit+testng.available}"/>
1.20 </condition>
1.21 + <property name="java.failonerror" value="true"/>
1.22 </target>
1.23 <target name="-post-init">
1.24 <!-- Empty placeholder for easier customization. -->
1.25 @@ -693,7 +699,7 @@
1.26 <sequential>
1.27 <property environment="env"/>
1.28 <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/>
1.29 - <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}">
1.30 + <java classname="@{classname}" dir="${profiler.info.dir}" failonerror="${java.failonerror}" fork="true" jvm="${profiler.info.jvm}">
1.31 <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
1.32 <jvmarg value="${profiler.info.jvmargs.agent}"/>
1.33 <jvmarg line="${profiler.info.jvmargs}"/>
1.34 @@ -768,7 +774,7 @@
1.35 <attribute default="${debug.classpath}" name="classpath"/>
1.36 <element name="customize" optional="true"/>
1.37 <sequential>
1.38 - <java classname="@{classname}" dir="${work.dir}" fork="true">
1.39 + <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
1.40 <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
1.41 <jvmarg line="${debug-args-line}"/>
1.42 <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
1.43 @@ -795,7 +801,7 @@
1.44 <attribute default="jvm" name="jvm"/>
1.45 <element name="customize" optional="true"/>
1.46 <sequential>
1.47 - <java classname="@{classname}" dir="${work.dir}" fork="true">
1.48 + <java classname="@{classname}" dir="${work.dir}" failonerror="${java.failonerror}" fork="true">
1.49 <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
1.50 <jvmarg value="-Dfile.encoding=${runtime.encoding}"/>
1.51 <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/>
2.1 --- a/java/reflexe/nbproject/genfiles.properties Sat Nov 19 22:28:08 2016 +0100
2.2 +++ b/java/reflexe/nbproject/genfiles.properties Sat Nov 19 22:29:10 2016 +0100
2.3 @@ -4,5 +4,5 @@
2.4 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
2.5 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
2.6 nbproject/build-impl.xml.data.CRC32=cd87ef88
2.7 -nbproject/build-impl.xml.script.CRC32=1e64564b
2.8 -nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
2.9 +nbproject/build-impl.xml.script.CRC32=5b12b8e1
2.10 +nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48
3.1 --- a/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:28:08 2016 +0100
3.2 +++ b/java/reflexe/src/cz/frantovo/příklady/reflexe/Reflexe.java Sat Nov 19 22:29:10 2016 +0100
3.3 @@ -3,6 +3,9 @@
3.4 import java.lang.reflect.Field;
3.5 import java.math.BigDecimal;
3.6 import java.math.RoundingMode;
3.7 +import java.util.Map;
3.8 +import java.util.Objects;
3.9 +import java.util.concurrent.ConcurrentHashMap;
3.10 import java.util.function.Consumer;
3.11
3.12 /**
3.13 @@ -16,6 +19,9 @@
3.14 private static final RoundingMode ZAOKROUHLOVÁNÍ = RoundingMode.UP;
3.15 private static final int PŘESNOST_PROCENT = 2;
3.16
3.17 + private static final Map<KlíčTřídaPole, Field> známáPole = new ConcurrentHashMap<>();
3.18 + private static final Map<Class, Map<String, Field>> známáPole2 = new ConcurrentHashMap<>();
3.19 +
3.20 private static void nastav(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
3.21 Field f = objekt.getClass().getDeclaredField(proměnná);
3.22 f.setAccessible(true);
3.23 @@ -23,6 +29,67 @@
3.24 // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
3.25 }
3.26
3.27 + private static void nastavOptimalizovaně(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
3.28 +
3.29 + KlíčTřídaPole klíč = new KlíčTřídaPole(objekt.getClass(), proměnná);
3.30 + Field f = známáPole.get(klíč);
3.31 +
3.32 + if (f == null) {
3.33 + f = objekt.getClass().getDeclaredField(proměnná);
3.34 + f.setAccessible(true);
3.35 + známáPole.put(klíč, f);
3.36 + }
3.37 +
3.38 + f.set(objekt, hodnota);
3.39 + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
3.40 + }
3.41 +
3.42 + private static class KlíčTřídaPole {
3.43 +
3.44 + private final Class třída;
3.45 + private final String pole;
3.46 +
3.47 + public KlíčTřídaPole(Class třída, String pole) {
3.48 + this.třída = třída;
3.49 + this.pole = pole;
3.50 + }
3.51 +
3.52 + @Override
3.53 + public boolean equals(Object obj) {
3.54 + if (obj instanceof KlíčTřídaPole) {
3.55 + KlíčTřídaPole druhýKlíč = (KlíčTřídaPole) obj;
3.56 + return Objects.equals(třída, druhýKlíč.třída) && Objects.equals(pole, druhýKlíč.pole);
3.57 + } else {
3.58 + return false;
3.59 + }
3.60 + }
3.61 +
3.62 + @Override
3.63 + public int hashCode() {
3.64 + return Objects.hash(třída, pole);
3.65 + }
3.66 +
3.67 + }
3.68 +
3.69 + private static void nastavOptimalizovaně2(Object objekt, String proměnná, Object hodnota) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
3.70 +
3.71 + Map<String, Field> mapaPolí = známáPole2.get(objekt.getClass());
3.72 + if (mapaPolí == null) {
3.73 + mapaPolí = new ConcurrentHashMap<>();
3.74 + známáPole2.put(objekt.getClass(), mapaPolí);
3.75 + }
3.76 +
3.77 + Field f = mapaPolí.get(proměnná);
3.78 + if (f == null) {
3.79 + f = objekt.getClass().getDeclaredField(proměnná);
3.80 + f.setAccessible(true);
3.81 + mapaPolí.put(proměnná, f);
3.82 + }
3.83 +
3.84 + f.set(objekt, hodnota);
3.85 + // TODO: můžeme odchytávat výjimky a vyhazovat vlastní výjimku případně běhovou
3.86 + }
3.87 +
3.88 private static void testSetter(int početOpakování) {
3.89 NějakáTřída t = new NějakáTřída();
3.90 for (int i = 0; i < početOpakování; i++) {
3.91 @@ -48,6 +115,28 @@
3.92 }
3.93 }
3.94
3.95 + private static void testReflexeOptimalizovaná(int početOpakování) {
3.96 + NějakáTřída t = new NějakáTřída();
3.97 + try {
3.98 + for (int i = 0; i < početOpakování; i++) {
3.99 + nastavOptimalizovaně(t, NÁZEV_PROMĚNNÉ, i);
3.100 + }
3.101 + } catch (Exception e) {
3.102 + throw new RuntimeException("test se nezdařil", e);
3.103 + }
3.104 + }
3.105 +
3.106 + private static void testReflexeOptimalizovaná2(int početOpakování) {
3.107 + NějakáTřída t = new NějakáTřída();
3.108 + try {
3.109 + for (int i = 0; i < početOpakování; i++) {
3.110 + nastavOptimalizovaně2(t, NÁZEV_PROMĚNNÉ, i);
3.111 + }
3.112 + } catch (Exception e) {
3.113 + throw new RuntimeException("test se nezdařil", e);
3.114 + }
3.115 + }
3.116 +
3.117 private static void testReflexePřipravená(int početOpakování) {
3.118 NějakáTřída t = new NějakáTřída();
3.119 try {
3.120 @@ -72,7 +161,7 @@
3.121 }
3.122
3.123 private static Long testuj(String názevTestu, int početOpakování, Long časProPorovnání, Consumer<Integer> test) {
3.124 - System.out.print("TEST: " + lpad(20, názevTestu) + ": ");
3.125 + System.out.print("TEST: " + lpad(24, názevTestu) + ": ");
3.126 try {
3.127 long začátek = System.currentTimeMillis();
3.128 test.accept(početOpakování);
3.129 @@ -92,7 +181,9 @@
3.130 long základníČas = testuj("přímý přístup", POČET_OPAKOVÁNÍ, null, Reflexe::testPřímýPřístup);
3.131 testuj("setter", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testSetter);
3.132 testuj("reflexe", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexe);
3.133 + testuj("reflexe optimalizovaná 1", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná);
3.134 + testuj("reflexe optimalizovaná 2", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexeOptimalizovaná2);
3.135 testuj("reflexe připravená", POČET_OPAKOVÁNÍ, základníČas, Reflexe::testReflexePřipravená);
3.136 }
3.137
3.138 -}
3.139 \ No newline at end of file
3.140 +}