void () { System.out.println("--- JavaFX default property values ---"); final Map<String, Map<String, DefaultValue>> defaultPropertyValues = new TreeMap<>(); final Map<String, Map<String, String>> declaredProperties = new TreeMap<>(); final Map<String, Map<String, Set<String>>> overriddenProperties = new TreeMap<>(); final Map<String, String> superClasses = new TreeMap<>(); try (final ZipInputStream zip = new ZipInputStream(new FileInputStream(BINARIES_PATH))) { for (ZipEntry ze = zip.getNextEntry(); ze != null; ze = zip.getNextEntry()) { final String entryName = ze.getName(); if (!ze.isDirectory() && entryName.endsWith(".class") && entryName.startsWith("javafx")) { final String className = entryName.substring(0, entryName.lastIndexOf('.')).replace('/', '.'); Class<?> currentClass = Class.forName(className); if (!Modifier.isPublic(currentClass.getModifiers()) && !Modifier.isProtected(currentClass.getModifiers())) continue; if (currentClass.getName().startsWith("javafx.beans")) continue; if (currentClass.getName().matches(".*\\$\\d+$")) continue; BeanInfo info = Introspector.getBeanInfo(currentClass); if (currentClass.getSuperclass() != null) { superClasses.put(currentClass.getName(), currentClass.getSuperclass().getName()); } Set<String> bindings = new TreeSet<>(); for (MethodDescriptor methodDesc : info.getMethodDescriptors()) { if (methodDesc.getName().endsWith("Property") && !methodDesc.getMethod().getGenericReturnType().toString().contains("ReadOnly")) { bindings.add(methodDesc.getName()); } } Map<String, Object> constructorNamedArgValues = constructorNamedArgValues(currentClass); Object instance = null; for (PropertyDescriptor desc : info.getPropertyDescriptors()) { final String propName = desc.getName(); final String propQualifiedName = currentClass.getName() + "#" + propName; if (ourSkippedProperties.contains(propQualifiedName)) continue; final Method setter = desc.getWriteMethod(); final boolean hasBinding = bindings.contains(propName + "Property"); final Object value; final Class<?> declaringClass; final Type type; if (setter != null && hasBinding && (type = setter.getGenericParameterTypes()[0]) instanceof Class && isSupportedPropertyType((Class)type)) { if (instance == null) { instance = instantiate(currentClass); if (instance == null) break; } final Method getter = desc.getReadMethod(); try { value = getter.invoke(instance); } catch (IllegalAccessException | InvocationTargetException e) { throw new RuntimeException("Can't invoke " + getter + " on " + currentClass, e); } declaringClass = getter.getDeclaringClass(); } else { value = constructorNamedArgValues.get(propName); if (value == null) continue; declaringClass = currentClass; } if (value != null) { final DefaultValue newValue = new DefaultValue(value, declaringClass.getName()); if (declaringClass.getName().startsWith("javafx")) { defaultPropertyValues .computeIfAbsent(currentClass.getName(), unused -> new TreeMap<>()) .put(propName, newValue); } final Map<String, String> shareableProperties = declaredProperties.computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()); final String sharedValue = shareableProperties.get(propName); if (sharedValue == null) { shareableProperties.put(propName, newValue.getValueText()); } else if (!sharedValue.equals(newValue.getValueText())) { final Set<String> multipleValues = overriddenProperties .computeIfAbsent(declaringClass.getName(), unused -> new TreeMap<>()) .computeIfAbsent(propName, unused -> new TreeSet<>()); multipleValues.add(sharedValue); multipleValues.add(newValue.getValueText()); } } } } } } catch (IOException | ClassNotFoundException | IntrospectionException e) { e.printStackTrace(); } System.out.println("-------- Collected from sources ---------"); ourFromSource.forEach((qualifiedPropName, value) -> System.out.println(qualifiedPropName + "=" + value)); System.out.println("-------- Shared (not overridden) ---------"); declaredProperties.forEach( (className, propertyMap) -> { final Map<String, Set<String>> multipleValues = overriddenProperties.getOrDefault(className, Collections.emptyMap()); propertyMap.forEach((propName, valueText) -> { if (!multipleValues.containsKey(propName)) { System.out.println(className + "#" + propName + "=" + valueText); } }); }); System.out.println("-------- Overridden in subclass ---------"); final Map<String, Map<String, DefaultValue>> fromSource = new TreeMap<>(); ourFromSource.forEach((qualifiedPropName, value) -> { final int p = qualifiedPropName.indexOf('#'); if (p > 0) { final String className = qualifiedPropName.substring(0, p); final String propName = qualifiedPropName.substring(p + 1); fromSource.computeIfAbsent(className, unused -> new TreeMap<>()) .computeIfAbsent(propName, unused -> new DefaultValue(value, className)); } }); defaultPropertyValues.forEach( (className, propertyMap) -> propertyMap.forEach( (propName, propValue) -> { final DefaultValue sourceValue = fromSource.getOrDefault(className, Collections.emptyMap()).get(propName); if (sourceValue != null && areValuesEqual(propValue, sourceValue)) { return; } final Map<String, Set<String>> multipleValues = overriddenProperties.get(propValue.getDeclaringClass()); if (multipleValues != null && multipleValues.get(propName) != null) { boolean sameValueInSuperClass = false; for (String scName = superClasses.get(className); scName != null; scName = superClasses.get(scName)) { final Map<String, DefaultValue> superPropMap = defaultPropertyValues.getOrDefault(scName, fromSource.get(scName)); if (superPropMap != null) { DefaultValue superValue = superPropMap.get(propName); if (superValue != null) { sameValueInSuperClass = areValuesEqual(propValue, superValue); break; } } } if (!sameValueInSuperClass) { System.out.println(className + "#" + propName + "=" + propValue.getValueText()); } } })); System.out.println("-------- Overridden properties' values ---------"); overriddenProperties .forEach((className, propertyValues) -> propertyValues .forEach((key, value) -> System.out.println("-- " + className + "#" + key + value))); System.out.println("-------- Skipped properties ---------"); ourSkippedProperties.forEach(propName -> System.out.println("-- " + propName)); }