2010-07-26 34 views
19

Tôi đang tìm cách nhúng một đoạn mã sẽ in ra thời gian khi lớp hiện tại được biên dịch lần cuối. Làm thế nào điều này có thể được thực hiện trong Java?Thời gian in Java của quá trình biên dịch cuối cùng

+0

Đối với những gì lý do là ngày lập quan tâm? –

+1

@MichaelKonietzka là có một cách kinh điển để lấy số phiên bản của một JAR tại thời gian chạy? – uprego

Trả lời

11

Không có hỗ trợ trực tiếp cho điều này trong java, vì không có tiền xử lý. Tương đương gần nhất là thuộc tính "Build-Date" trong tệp kê khai JAR. Nhiều hệ thống xây dựng thêm thuộc tính này theo mặc định hoặc cung cấp phương tiện để thêm thuộc tính này.

Sau đó, bạn có thể đọc tệp kê khai của JAR trong thời gian chạy để nhận ngày. Câu trả lời cho số SO question này mô tả cách đọc các giá trị từ tệp kê khai JAR.

Cách khác là sử dụng tính năng lọc tài nguyên để thêm ngày vào tệp thuộc tính, sau đó được đọc khi chạy. Điều này khá độc đáo, phi tiêu chuẩn và nếu bạn có nhiều lọ, với thời gian biên dịch khác nhau, thì điều này nhanh chóng trở nên khó quản lý, trừ khi bạn có thể đưa yếu tố này vào một phần chung của tất cả các lọ được xây dựng.

+1

+1. Tôi đã tìm kiếm một tài sản biểu hiện tiêu chuẩn nhưng không tìm thấy nó trong thời gian tốt. –

4

Tạo một kịch bản shell mà cập nhật mã lớp với thời gian biên dịch bằng cách thay thế placeholders đặc biệt:

public final class CompilationInfo 
{ 
    public static final String TIME = "$COMPILE_TIME"; 
} 

Mọi chi tiết, thấy this article.

+1

Chúng tôi muốn tạo StackOverflow kho lưu trữ thông tin của riêng mình. Bạn có thể giải thích và đưa ra một ví dụ ở đây, hoặc ít nhất là tóm tắt? –

+0

Đây là liên kết đến thông điệp mà SO nên chấp nhận: http://groups.google.com/group/comp.lang.java.help/msg/5177eeaea2ef9ad9?hl=vi –

+0

Đã sửa lỗi, cảm ơn. – spektom

1

Không biết cách tiêu chuẩn để làm điều này, đề xuất của tôi tương tự như liên kết của spektom nhưng sẽ thêm tệp thuộc tính vào jar được điền bởi tập lệnh xây dựng của bạn (Ant có một tác vụ tích hợp để tạo thuộc tính tập tin). Có thể đặt nó tại /buildinfo.properties. Sau đó, tạo một lớp Java chỉ đơn giản là thăm dò tệp thuộc tính đó khi chạy.

Trong Ant, nó có thể trông giống như thế này:

... 
<tstamp/>  
... 
<propertyfile file="${output.dir}/buildinfo.properties"> 
    <entry key="build.date" value="${TSTAMP}"/> 
</propertyfile> 

Và sau đó tương ứng Java

public Date getBuildDate() { 
    Properties buildProps = new Properties(); 
    buildProps.load(getClass().getResourceAsStream("/buildinfo.properties")); 
    return someConversion(buildProps.getProperty("build.date")); 
} 
1

Hãy thủ tục xây dựng của bạn tạo ra một tập tin bất động sản có chứa các thông tin mà bạn cần, và sau đó đọc các tính chất như một nguồn lực trong mã của bạn

5

Đó là một chút thời gian, nhưng bạn có thể làm điều này với lọc Ant.

Pop phương pháp sau đây trong lớp học của bạn:

public static String timeBuilt(){ 
    return "Built at @[email protected] on @[email protected]"; 
} 

Rồi đặt sau đây trong Ant xây dựng tập tin của bạn.

<target name="get-time"> 
    <tstamp> 
     <format property="buildTime" pattern="HH:mm:ss" locale="en,UK"/> 
     <format property="buildDate" pattern="dd-MM-yyyy" locale="en,UK"/> 
    </tstamp> 
</target> 

<target name="copy-files" depends="get-time"> 
    <filter token="timeBuilt" value="${buildTime}"/> 
    <filter token="dateBuilt" value="${buildDate}"/> 
    <copy includeemptydirs="false" todir="build" filtering="true"> 
     <fileset dir="src"/> 
    </copy> 
</target> 

này sẽ sao chép tất cả mọi thứ trong "src" thư mục để "xây dựng" và khi làm như vậy sẽ thay thế @ timeBuilt @ và @ dateBuilt @ với thời gian và ngày tháng năm xây dựng, tương ứng. Chỉ cần tạo mục tiêu xây dựng của bạn phụ thuộc vào các tệp sao chép và xây dựng từ thư mục "xây dựng" - không phải thư mục "src".

Lợi thế của việc thay thế nội dung của phương pháp tĩnh là thao tác này sẽ hoạt động trên cơ sở mỗi lớp - nếu bạn lấy tệp lớp được tạo và kết hợp chúng với một số tệp lớp khác được xây dựng tại một thời điểm khác, họ sẽ biết khi nào chúng được xây dựng. Các tệp thuộc tính là hợp lý, nhưng trừ khi bạn có nhiều tệp thuộc tính, bạn sẽ chỉ có thể có thời gian xây dựng cho toàn bộ gói.

8

Vì đây không bao giờ được đề cập, bất cứ ai tìm cách để giải quyết vấn đề này bằng bất kỳ phương tiện cần thiết, có thể tìm thấy điều này như một thích hợp, tuy nhiên hacky, giải pháp:

new Date(new File(getClass().getClassLoader().getResource(getClass().getCanonicalName().replace('.', '/') + ".class").toURI()).lastModified())) 

Nó có thể không được khá, và nó rất tốt có thể không tương thích trên các nền tảng khác, nhưng đây là cách duy nhất tôi tìm thấy để tìm ra ngày biên dịch của lớp hiện tại trong Java nguyên gốc.

+0

tôi thích nó; trong mắt tôi, cách tiếp cận này không phải là một hack. –

12

Câu hỏi này đã được trả lời từ lâu. Nhưng trong trường hợp một người nào đó thay đổi bởi đây là một giải pháp phù hợp với tôi, tương tự như những gì Supah Fly đề nghị nhưng hỗ trợ jar và file.

private long classBuildTimeMillis() throws URISyntaxException, IllegalStateException, IllegalArgumentException { 
    URL resource = getClass().getResource(getClass().getSimpleName() + ".class"); 
    if (resource == null) { 
     throw new IllegalStateException("Failed to find class file for class: " + 
             getClass().getName()); 
    } 

    if (resource.getProtocol().equals("file")) { 

     return new File(resource.toURI()).lastModified(); 

    } else if (resource.getProtocol().equals("jar")) { 

     String path = resource.getPath(); 
     return new File(path.substring(5, path.indexOf("!"))).lastModified(); 

    } else { 

     throw new IllegalArgumentException("Unhandled url protocol: " + 
       resource.getProtocol() + " for class: " + 
       getClass().getName() + " resource: " + resource.toString()); 
    } 
} 

Nhưng điều này sẽ không xử lý tệp zip hoặc ngữ cảnh tĩnh và nó ném ngoại lệ thay vì trả lại giá trị nếu mọi thứ ở phía nam. Điều này thân thiện hơn một chút:

private static final Date buildDate = getClassBuildTime(); 

/** 
* Handles files, jar entries, and deployed jar entries in a zip file (EAR). 
* @return The date if it can be determined, or null if not. 
*/ 
private static Date getClassBuildTime() { 
    Date d = null; 
    Class<?> currentClass = new Object() {}.getClass().getEnclosingClass(); 
    URL resource = currentClass.getResource(currentClass.getSimpleName() + ".class"); 
    if (resource != null) { 
     if (resource.getProtocol().equals("file")) { 
      try { 
       d = new Date(new File(resource.toURI()).lastModified()); 
      } catch (URISyntaxException ignored) { } 
     } else if (resource.getProtocol().equals("jar")) { 
      String path = resource.getPath(); 
      d = new Date(new File(path.substring(5, path.indexOf("!"))).lastModified());  
     } else if (resource.getProtocol().equals("zip")) { 
      String path = resource.getPath(); 
      File jarFileOnDisk = new File(path.substring(0, path.indexOf("!"))); 
      //long jfodLastModifiedLong = jarFileOnDisk.lastModified(); 
      //Date jfodLasModifiedDate = new Date(jfodLastModifiedLong); 
      try(JarFile jf = new JarFile (jarFileOnDisk)) { 
       ZipEntry ze = jf.getEntry (path.substring(path.indexOf("!") + 2));//Skip the ! and the/
       long zeTimeLong = ze.getTime(); 
       Date zeTimeDate = new Date(zeTimeLong); 
       d = zeTimeDate; 
      } catch (IOException|RuntimeException ignored) { } 
     } 
    } 
    return d; 
} 
+3

Câu trả lời cũ này không xử lý các tệp zip cho một cái gì đó như tệp chiến dịch được triển khai trên weblogic chẳng hạn, và nó ném ngoại lệ thay vì trả về null của ngày không thể xác định được và nó không xử lý ngữ cảnh tĩnh. Nhưng tôi đã sửa đổi nó để làm điều đó :). – ggb667

0

Đây là lớp của tôi để phát hiện thời gian xây dựng chương trình Java của bạn. Nó cũng sử dụng mã từ câu trả lời this.

import java.io.File; 
import java.io.IOException; 
import java.net.URISyntaxException; 
import java.net.URL; 
import java.nio.file.attribute.FileTime; 
import java.text.DateFormat; 
import java.util.Date; 
import java.util.Enumeration; 
import java.util.Locale; 
import java.util.jar.JarFile; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 

public class BuildDate 
{ 
    private static Date buildDate; 

    static 
    { 
     try 
     { 
      buildDate = setBuildDate(); 
     } catch (Exception exception) 
     { 
      exception.printStackTrace(); 
     } 
    } 

    public static String getBuildDate() 
    { 
     int style = DateFormat.FULL; 
     Locale locale = Locale.getDefault(); 
     DateFormat dateFormat = DateFormat.getDateInstance(style, locale); 
     DateFormat timeFormat = DateFormat.getTimeInstance(style, locale); 

     return dateFormat.format(buildDate) + " " + timeFormat.format(buildDate); 
    } 

    private static Date setBuildDate() throws Exception 
    { 
     if (ProgramDirectoryUtilities.runningFromIntelliJ()) 
     { 
      return getClassBuildTime(); 
     } else 
     { 
      return getNewestFileDate(); 
     } 
    } 

    private static Date getNewestFileDate() throws Exception 
    { 
     String filePath = ProgramDirectoryUtilities.getJARFilePath(); 
     File file = new File(filePath); 
     ZipFile zipFile = new ZipFile(file); 
     Enumeration entries = zipFile.entries(); 

     long millis = -1; 

     while (entries.hasMoreElements()) 
     { 
      ZipEntry entry = (ZipEntry) entries.nextElement(); 

      if (!entry.isDirectory()) 
      { 
       FileTime fileTime = entry.getLastModifiedTime(); 
       long currentMillis = fileTime.toMillis(); 

       if (millis < currentMillis) 
       { 
        millis = currentMillis; 
       } 
      } 
     } 

     return new Date(millis); 
    } 

    /** 
    * Handles files, jar entries, and deployed jar entries in a zip file (EAR). 
    * 
    * @return The date if it can be determined, or null if not. 
    */ 
    private static Date getClassBuildTime() throws IOException, URISyntaxException 
    { 
     Date date = null; 
     Class<?> currentClass = new Object() 
     { 
     }.getClass().getEnclosingClass(); 
     URL resource = currentClass.getResource(currentClass.getSimpleName() + ".class"); 
     if (resource != null) 
     { 
      switch (resource.getProtocol()) 
      { 
       case "file": 
        date = new Date(new File(resource.toURI()).lastModified()); 
        break; 
       case "jar": 
       { 
        String path = resource.getPath(); 
        date = new Date(new File(path.substring(5, path.indexOf("!"))).lastModified()); 
        break; 
       } 
       case "zip": 
       { 
        String path = resource.getPath(); 
        File jarFileOnDisk = new File(path.substring(0, path.indexOf("!"))); 
        try (JarFile jarFile = new JarFile(jarFileOnDisk)) 
        { 
         ZipEntry zipEntry = jarFile.getEntry(path.substring(path.indexOf("!") + 2));//Skip the ! and the/
         long zeTimeLong = zipEntry.getTime(); 
         date = new Date(zeTimeLong); 
        } 
        break; 
       } 
      } 
     } 
     return date; 
    } 
} 

Utility lớp:

import java.io.File; 
import java.lang.invoke.MethodHandles; 
import java.net.URISyntaxException; 
import java.net.URLDecoder; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipFile; 

public class ProgramDirectoryUtilities 
{ 
    public static String getJARFilePath() throws URISyntaxException 
    { 
     return new File(MethodHandles.lookup().lookupClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getAbsolutePath(); 
    } 

    public static boolean runningFromJAR() 
    { 
     try 
     { 
      String jarFilePath = new File(MethodHandles.lookup().lookupClass().getProtectionDomain() 
        .getCodeSource() 
        .getLocation() 
        .getPath()). 
        toString(); 
      jarFilePath = URLDecoder.decode(jarFilePath, "UTF-8"); 

      try (ZipFile zipFile = new ZipFile(jarFilePath)) 
      { 
       ZipEntry zipEntry = zipFile.getEntry("META-INF/MANIFEST.MF"); 

       return zipEntry != null; 
      } 
     } catch (Exception exception) 
     { 
      return false; 
     } 
    } 

    public static String getProgramDirectory() 
    { 
     if (runningFromJAR()) 
     { 
      return getCurrentJARDirectory(); 
     } else 
     { 
      return getCurrentProjectDirectory(); 
     } 
    } 

    private static String getCurrentProjectDirectory() 
    { 
     return new File("").getAbsolutePath(); 
    } 

    private static String getCurrentJARDirectory() 
    { 
     try 
     { 
      return new File(MethodHandles.lookup().lookupClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParent(); 
     } catch (URISyntaxException exception) 
     { 
      exception.printStackTrace(); 
     } 

     return null; 
    } 

    public static boolean runningFromIntelliJ() 
    { 
     String classPath = System.getProperty("java.class.path"); 
     return classPath.contains("idea_rt.jar"); 
    } 
} 
Các vấn đề liên quan